javascript - 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);
}
然后,您可以构建所有 Promise 的链,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]));
});
}
请注意,在该循环中使用const
orlet
而不是var
for很重要,因为回调会关闭它;请参阅此问题的答案以了解原因并使其发挥作用。foo
then
const
let
每次调用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();
推荐阅读
- javascript - 在 ReactJS 中使用 this 的动态变量名
- html - 如何在客户端使用 CSS 文件?
- vue.js - Nuxt.js Vuetify v-img 组件不生成 img 标签
- java - Java中的错误处理在阿里云中捕获和引发事件
- twilio - 有没有办法知道是否有人阻止/将我的 twilio 号码列入黑名单?
- vaadin - 如何使 vaadin-app-layout 中的 vaadin-drawer-toggle 默认关闭?
- android - Apple使用FireBase Auth登录android有问题
- java - 如何包含依赖项目 maven 中的 .class 文件?
- c++ - C++ 值作为映射:第二个映射中的值未更新
- unity3d - 我们如何在 4 个固定位置从预制件列表中随机生成 1 个选定预制件和 3 个随机预制件?