简体   繁体   中英

Async await in map function not executing in order

I have the follow code below:

 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);

My question is in the order of the console.log's I am getting:

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) [{…}, {…}, {…}, {…}]

Why is the Third log being printed before all the Second console.log are done? Is this because I am using recursion inside of the asyncInMap function along with async/await ? Ideally the asyncInMap should be completed (with all the Second logs printed first) and then only the Third log should be printed correct?

that is the feature of async await code in js. THIRD will be called earlier than any asynchronious operation inside of that call, because event loop works like that in js. But there is a mistake in your code that can make FOURTH be logged earlier than all of the SECOND s are complete, because you are not waiting till recursive SECOND s are completed anywhere. To fix that you could add await here

elem.recursion = await Promise.all(asyncInMap(elem.recursiveArray));

also if you would like to persist the order of execution, you could do simple iterations and do all the awaiting logic at the function top level

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);

note, that in the last example there will be no parallel operation executing at the same time. they will be "async called" one by one in a predefined order

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM