如何在javascript中同步调用一组函数

Nic*_*k P 4 javascript asynchronous synchronous synchronize

我正在开发一个需要获取一些数据并处理它的javascript项目,但我遇到了JavaScript异步性质的问题.我想要做的是如下所示.

//The set of functions that I want to call in order
function getData() {
    //gets the data
}

function parseData() {
    //does some stuff with the data
}

function validate() {
    //validates the data
}

//The function that orchestrates these calls 
function runner() {
    getData();
    parseData();
    validate();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我希望每个函数在继续下一次调用之前等待完成,因为我遇到程序在检索之前尝试验证数据的情况.但是,我还希望能够从这些函数返回一个值进行测试,所以我不能让这些函数返回一个布尔值来检查完成.在进入下一个调用之前,如何让javascript等待函数运行完成?

m-a*_*n-o 9

使用承诺:

//The set of functions that I want to call in order
function getData(initialData) {
  //gets the data
  return new Promise(function (resolve, reject) {
    resolve('Hello World!')
  })
}

function parseData(dataFromGetDataFunction) {
  //does some stuff with the data
  return new Promise(function (resolve, reject) {
    resolve('Hello World!')
  })
}

function validate(dataFromParseDataFunction) {
  //validates the data
  return new Promise(function (resolve, reject) {
    resolve('Hello World!')
  })
}

//The function that orchestrates these calls 
function runner(initialData) {
    return getData(initialData)
        .then(parseData)
        .then(validate)
}

runner('Hello World!').then(function (dataFromValidateFunction) {
    console.log(dataFromValidateFunction);
})
Run Code Online (Sandbox Code Playgroud)

它们不仅容易掌握,而且从代码可读性的角度来看也很有意义.在这里阅读更多相关信息.如果您在浏览器环境中,我建议使用 polyfill.


T.J*_*der 5

您引用的代码将同步运行。JavaScript 函数调用是同步的。

所以我会认为getDataparseData和/或validate涉及异步操作(如在浏览器中,或使用AJAXreadFile中的NodeJS)。如果是这样,您基本上有两个选项,这两个选项都涉及callbacks

第一个是让这些函数接受它们在完成时调用的回调,例如:

function getData(callback) {
    someAsyncOperation(function() {
        // Async is done now, call the callback with the data
        callback(/*...some data...*/);
    });
}
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它:

getData(function(data) {
    // Got the data, do the next thing
});
Run Code Online (Sandbox Code Playgroud)

回调的问题在于它们很难组合并且具有相当脆弱的语义。所以发明了promise来给它们更好的语义。在 ES2015(又名“ES6”)或一个像样的承诺库中,它看起来像这样:

function getData(callback) {
    return someAsyncOperation();
}
Run Code Online (Sandbox Code Playgroud)

或者如果someAsyncOperation未启用承诺,则:

function getData(callback) {
    return new Promise(function(resolve, reject) {
        someAsyncOperation(function() {
            // Async is done now, call the callback with the data
            resolve(/*...some data...*/);
            // Or if it failed, call `reject` instead
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

似乎对你没有多大作用,但关键之一是可组合性;你的最终函数看起来像这样:

function runner() {
    return getData()
        .then(parseData) // Yes, there really aren't () on parseData...
        .then(validate); // ...or validate
}
Run Code Online (Sandbox Code Playgroud)

用法:

runner()
    .then(function(result) {
         // It worked, use the result
    })
    .catch(function(error) {
         // It failed
    });
Run Code Online (Sandbox Code Playgroud)

这是一个例子;它只能在支持PromiseES2015 和 ES2015 箭头函数的相当新的浏览器上工作,因为我很懒惰,用箭头函数编写它并且没有包含 Promise 库:

function getData(callback) {
    someAsyncOperation(function() {
        // Async is done now, call the callback with the data
        callback(/*...some data...*/);
    });
}
Run Code Online (Sandbox Code Playgroud)
getData(function(data) {
    // Got the data, do the next thing
});
Run Code Online (Sandbox Code Playgroud)