javascript - for 循环不等待异步代码完成
问题描述
我有一个 for 循环,其中有一个函数调用,并且该函数还有一些异步代码。现在的问题是 for 循环不会等待异步代码从嵌套函数调用返回并继续迭代。
该函数aFunctionThatRunsAsync
来自我无法控制的库。
以下是所有代码。
// arr.length = 2
for (let i in arr) {
console.log(i, 'i1')
functionOne(arr[i], i, (err, res) => {
console.log(res)
})
}
function functionOne(inp, idx, callback) {
console.log(idx, 'i1')
const processor = aFunctionThatRunsAsync(inp, err => {
if (err) return callback(err);
});
processor.on('complete', data => {
console.log(data, idx, 'i3')
return callback(null, data)
});
}
问题:
代码执行后的日志是这样的:
0 i1 // expected
0 i2 // expected
1 i1 // unexpected, expected to have logged: data(obj) i3
1 i2 // unexpected, expected to have logged: 1 i1
最后记录:
data(obj) 0 i3
data(obj) 1 i3 // Not always in the same order
我希望 for 循环等待异步代码返回/记录并以正确的顺序同步运行,因此最终输出如下所示:
0 i1
0 i2
data(obj) 0 i3
1 i1
1 i2
data(obj) 1 i3
解决方案
该代码中没有任何内容for-in
可以让它等待那些回调。
中的代码functionOne
看起来不是基于 Promise 的,因此除非您想更改该代码,否则您需要在开始下一次迭代之前等待回调,如下所示:
process(0);
function process(i) {
if (i < arr.length) {
console.log(i, 'i1')
functionOne(arr[i], i, (err, res) => {
if (err) {
console.error(err);
// I assume you don't want to continue here
} else {
console.log(res);
process(i + 1);
}
});
}
}
或者,您可以做出functionOne
return 承诺:
function functionOne(inp, idx) {
return new Promise((resolve, reject) {
console.log(idx, 'i1')
const processor = aFunctionThatReturnsAPromise(inp, err => {
if (err) return reject(err);
});
processor.on('complete', data => {
console.log(data, idx, 'i3');
resolve(data);
});
})
}
然后:
let promise = Promise.resolve();
for (let i = 0; i < arr.length; ++i) {
promise = promise.then(() => (
functionOne(arr[i], i).then(res => {
console.log(res);
})
));
}
promise.catch(error => console.error(error));
请注意,let
里面for
很重要。不可能,而且必须var
在里面for
。那是因为我们需要传递给的回调来then
关闭fori
循环迭代,它会let
像上面那样使用,但不会使用var
.
在async
函数中使用会更容易:
// In an `async` function
try {
for (let i = 0; i < arr.length; ++i) {
console.log(await functionOne(arr[i], i));
}
} catch (error) {
console.error(error);
}
推荐阅读
- laravel - Laravel 队列进程超时
- sql - SQL 中的教科书 MergeSort 实现(Postgres)
- html - Microsoft Outlook 2019 的 HTML 条件
- php - QuickBooks Desktop 中的 SalesOrderQuery 不返回所有订单信息
- javascript - 奇怪的 JS 变量错误
- entity-framework - Ado.net 实体数据模型 - Crud 问题
- javascript - 如何将 API 信息放入 localStorage
- windows-services - Tomcat7 Windows 服务无法启动
- couchbase - 如何在沙发库的对象内添加索引和查询数组?
- javascript - 更改音频播放器功能变为具有 Pitch Shift 效果的 Live Web Audio Input