[英]for loop doesn't wait for async code to finish
I have a for loop in which there is a function call and that function further has some async code.我有一个 for 循环,其中有一个函数调用,并且该函数还有一些异步代码。 Now the issue is that the for loop doesn't wait for the async code to return from the nested function call and continues iterating.
现在的问题是 for 循环不等待异步代码从嵌套函数调用返回并继续迭代。
The function aFunctionThatRunsAsync
comes from a library that I have no control over.函数
aFunctionThatRunsAsync
来自一个我无法控制的库。
Below is all the code.下面是全部代码。
// 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)
});
}
Problem:问题:
The log looks like this after the execution of the code:代码执行后的日志是这样的:
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
And finally logs:最后记录:
data(obj) 0 i3
data(obj) 1 i3 // Not always in the same order
I want the for loop to wait for the async code to return/log and run synchronously in the correct order so the final output look like this:我希望 for 循环等待异步代码返回/记录并以正确的顺序同步运行,因此最终输出如下所示:
0 i1
0 i2
data(obj) 0 i3
1 i1
1 i2
data(obj) 1 i3
That code doesn't have anything in the for-in
to make it wait for those callbacks.该代码在
for-in
中没有任何内容使其等待这些回调。
The code in functionOne
doesn't look promise-based, so unless you want to change that code, you need to wait for the callback before starting the next iteration, something like this: 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);
}
});
}
}
Alternatively, you could make functionOne
return a promise:或者,您可以让
functionOne
返回一个承诺:
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);
});
})
}
Then:然后:
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));
Note that the let
inside the for
there is important.请注意,
for
there 里面的let
很重要。 It can't be var
, and it has to be inside the for
.它不能是
var
,它必须在for
。 That's because we need the callback we pass to then
to close over the i
for that loop iteration, which it will with let
as above but wouldn't with var
.那是因为我们需要传递给
then
的回调来关闭该循环迭代的i
,它会像上面那样使用let
但不会使用var
。
It would be easier to use in an async
function:在
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.