Node.js - 等待多个异步调用完成,然后再继续代码



所以基本上我有一个带有异步函数的 for 循环。问题是程序在循环后继续,我希望它等到循环中调用的所有异步函数完成,然后代码继续。

在我的代码中,"bar"是一个 json 数组,其中包含其他 json 数组。

function write(bla) { // gets called one after another
for(var url in bla) {
asyncFunctionCall(url); // Executed about 50 times, it has to run parallel
}
// Wait for all called functions to finish before next stuff happens and
// write gets called again.
}
for(var foo in bar) {
// Here i parse the json array "foo" which is in the json array "bar"
write(foo[bla]); // bla is an array of multiple urls.
}

异步函数调用如下所示:

var request = require('request');
request(url, function (error, response, body) {
if(typeof response !== 'undefined') {
if((response.statusCode >= 400 && response.statusCode <= 451)
|| (response.statusCode >= 500 && response.statusCode <= 511))
return true;
return false;
}
return false;
});

这里最简单的方法是直接或通过async/await语法使用 promise。在这种情况下,可能是直接的。

首先,你必须做出asyncFunctionCall回报一个承诺。看起来您总是返回一个布尔值,因此在这种情况下,我们将始终解决承诺:

function asyncFunctionCall(url) {
return new Promise(resolve => {
request(url, function (error, response, body) {
if(typeof response !== 'undefined') {
if((response.statusCode >= 400 && response.statusCode <= 451)
|| (response.statusCode >= 500 && response.statusCode <= 511)) {
resolve(true);
return;
}
}
resolve(false);
});
});
}

然后,建立一系列你的承诺,并使用Promise.all等待所有承诺完成。这些调用并行运行:

function write(bla) { // gets called one after another
const promises = [];
for(var url in bla) {
promises.push(asyncFunctionCall(url)); // Executed about 50 times.
}
return Promise.all(promises);
}

然后,您可以构建一个包含write所有承诺的链,以便它们串联运行:

let p = Promise.resolve();
for (const foo in bar) { // <== Notice `const`
// See "Edit" below
p = p.then(() => {
// Here i parse the json object "foo" in the json array "bar"
// bla is an array of multiple urls.
return write(foo[bla]));
});
}

请注意,在该循环中使用constlet而不是varfoo很重要,因为then回调会关闭它;请参阅此问题的答案,了解为什么constlet使其工作。

每次调用write只会在前一个工作完成后进行。

然后等待整个过程完成:

p.then(() => {
// All done
});

您没有使用write请求中的布尔值显示任何内容,但它们(作为数组(可用作write承诺的解析值。


该过程的第二部分,我们调用write,也可以用async函数编写,这可能会使逻辑流更清晰:

async function doTheWrites() {
for (const foo in bar) {
// Here i parse the json object "foo" in the json array "bar"
// bla is an array of multiple urls.
await write(foo[bla]);
}
}

然后整个过程:

doTheWrites().then(() => {
// All done
});

。或者,如果这也async函数中:

await doTheWrites();

使函数异步并等待调用:

async function write(foo) {
for(const url of foo) {
await asyncFunctionCall(url);
}  
}
(async function() {
for(const foo of bar) {
await  write(foo);
}
})()

这将执行一个又一个的请求。要并行执行它们,请使用 Promise.all:

const write = foo => Promise.all(foo.map(asyncFunctionCall));
Promise.all(bar.map(write))
.then(() => console.log("all done"));

相关内容

最新更新