我有以下代码:
var arr = [
{ condition: true, recursion: [], result: 'OLD_RESULT', recursiveArray: [{condition: true, result: 'OLD_RESULT'}] },
{condition: false, result: 'OLD_RESULT'},
{ condition: true, recursion: [], result: 'OLD_RESULT', recursiveArray: [{condition: true, result: 'OLD_RESULT'}] },
{condition: false, result: 'OLD_RESULT'},
];
var someAsyncCall = async () => {
return 'NEW VALUE';
};
var asyncInMap = (arr) => {
return arr.map(async (elem) => {
const condition = elem.condition;
if (condition) {
const result = await someAsyncCall();
elem.result = result;
}
if (elem.recursiveArray) {
elem.recursion = asyncInMap(elem.recursiveArray);
}
console.log('SECOND:', elem);
return elem;
});
};
console.log('FIRST');
var promisesVal = asyncInMap(arr);
console.log('THIRD');
var completedVal = await Promise.all(promisesVal);
console.log('FOURTH', completedVal);
我的问题是按照我得到的 console.log's
的顺序:
FIRST
SECOND: {condition: false, result: "OLD_RESULT"}
SECOND: {condition: false, result: "OLD_RESULT"}
THIRD
SECOND: {condition: true, recursion: Array(1), result: "NEW VALUE", recursiveArray: Array(1)}
SECOND: {condition: true, recursion: Array(1), result: "NEW VALUE", recursiveArray: Array(1)}
SECOND: {condition: true, result: "NEW VALUE"}
SECOND: {condition: true, result: "NEW VALUE"}
FOURTH (4) [{…}, {…}, {…}, {…}]
为什么在所有 Third
Second
完成之前打印 console.log
日志?这是因为我在 asyncInMap
函数中使用递归和 async/await
吗?理想情况下,asyncInMap
应该完成(首先打印所有 Second
日志)然后只有 Third
日志应该正确打印?
答案 0 :(得分:3)
这是js中async await
代码的特性。 THIRD
将比该调用中的任何异步操作更早地被调用,因为事件循环的工作方式与 js 中的一样。但是您的代码中存在一个错误,它可以使 FOURTH
在所有 SECOND
完成之前被记录,因为您没有等到递归 SECOND
在任何地方完成。要解决此问题,您可以在此处添加等待
elem.recursion = await Promise.all(asyncInMap(elem.recursiveArray));
此外,如果您想保持执行顺序,您可以进行简单的迭代并在函数顶层执行所有等待逻辑
var asyncInMap = async (arr) => {
for(const elem of arr) {
if(elem.condition) {
elem.result = await someAsyncCall();
}
if(elem.recursiveArray) elem.recursion = await asyncInMap(elem.recursiveArray);
console.log('SECOND:', elem);
}
return arr;
};
console.log('FIRST');
var promisesVal = asyncInMap(arr);
console.log('THIRD', 'calls can still be in progress here');
var completedVal = await promisesVal;
console.log('FOURTH', 'everything is completed here', completedVal);
请注意,在最后一个示例中,不会同时执行并行操作。它们将按照预定义的顺序一个一个地“异步调用”