Reputation: 137
Here's a simple async function:
async function f(){
let data = await (new Promise(r => setTimeout(r, 1000, 200)));
console.log(data)
return data + 100;
}
f()
console.log('me first');
Here's what's going to happen in this program:
So as you can see, I'm pretty comfortable with async await at this point! Now here's the code we have with for await of iteration!
async function f(){
let p1 = new Promise(function (r){
setTimeout(r, 2000, 1)
})
let p2 = new Promise(function (r){
setTimeout(r, 1000, 2)
})
let p3 = new Promise(function (r){
setTimeout(r, 500, 3)
})
let aop = [p1, p2, p3];
for await (let elem of aop ){
let data = await elem;
console.log(data)
}
}
f()
console.log('global');
Now intuitively, you would expect this to happen assuming the await will behave the same as it did inside our previous async function!
Upvotes: 2
Views: 338
Reputation: 14423
I can't talk to the specific implementations of jobs in each engine (or even polyfills) but creating promises shouldn't push code into a separate stack. The await
mechanism should do it.
Since we are talking about a regular iterable. The code shouldn't be that much different from:
console.log(await p1);
console.log(await p2);
console.log(await p3);
Precise semantics, are of course, not exactly the same. Order is still guaranteed by the iterator which is the main point. Even if p3
resolves first, the value is retrieved after it's awaited which happens after p2
and p1
are awaited.
Technically, each value that is a promise is being await
ed with for await(... of ...)
so, await
ing the value of the binding does nothing really (other than maybe pushing further code into the next stack).
E.g. you have console.log(await await p1);
Upvotes: 0
Reputation: 276506
For await loops have special behaviour when you get a promise.
Remember - promises are values - once you have a promise the action creating that promise (in this case setting up the timer) has already occurred. The promise is just the value+time for that action.
What happens here is actually:
for...await
.Symbol.asyncIterator
- the loop checks if it has a Symbol.iterator
. Since arrays are iterable and have that symbol - it is invoked.for... await
loop checks for each returned value if it's a promise - if it is it waits for it before progressing the loop.Since the values are promises - they will be ordered (that is, .next()
will be called on the iterator returned from [p1, p2, p3][Symbol.iterator]()
only after the previous promise returned from the previous .next
call has settled.
Note:
resolved
but mean settled
or fulfilled
.Upvotes: 1