Await works fine on async function, but not on promises

Multi tool use
Multi tool use


Await works fine on async function, but not on promises



I was playing with async/await and have found some strange discrepancy in the behavior, depending where await is called.


function test(msg) {
return new Promise(accept => {
console.log('in promise ', msg);
setTimeout(() => {
console.log('in timeout ', msg);
accept();
}, 1000)
});
}

async function run() {
await test('a');
await test('b');
}

run();



It outputs


in promise a
in timeout a
in promise B
in timeout B



, which is expected. However, if I move await inside "test" function, then the result is changed in a very unexpected manner:


async function test(msg) {
const promise = new Promise(accept => {
console.log('in promise ', msg);
setTimeout(() => {
console.log('in timeout ', msg);
accept();
}, 1000)
});
await promise;
}

function run() {
test('a');
test('B');
}

run();



Outputs


in promise a
in promise B
in timeout a
in timeout B



Could somebody please explain the behavior in the second case? Thank you.





Keep in ind that await doesn't block execution. It's just allows you to write code dealing with promises differently. await promise; in your example is actually completely useless. If you remove it or do promise.then(() => {}) instead (which is basically what await does) then you get the same result.
– Felix Kling
Jul 2 at 23:48



await


await promise;


promise.then(() => {})


await




5 Answers
5



When you construct a Promise, the body of that Promise executes immediately. That's why in the second piece of code, the console.logs inside of new Promise before the setTimeout occur right away.


console.log


new Promise


setTimeout



So why in the first example does it not do the same thing? It's because the second call to test isn't called until the first completes. The two Promises are essentially chained together, as though you wrote this:


test


return test('a').then(() => test('B'));



If you had done this:


const promiseA = test('a');
const promiseB = test('B');
await Promise.all([promiseA, promiseB]);



...you'd get the same result as the second block of code.





Thanks for the answer. The thing I cannot understand is why in the 2nd case the 2nd promise is constructed before first "await" elapses? Await should pause the execution of "test('a')", therefore "test('B')" shouldn't be called at all... or not?
– stillwaiting
Jul 3 at 0:04





await doesn't "pause" execution. It's just syntax for chaining things together. An async function becomes a function that returns a Promise. Unless you await that Promise by the caller, it won't appear to "pause."
– Jacob
Jul 3 at 0:06


await


Promise





(i.e., you still have to await the result of test(...); async/await doesn't make the asynchronous disappear, it just makes it more tolerable to deal with.)
– Jacob
Jul 3 at 0:07



await


test(...)



All the awaited Promises within an async function are executed (to completion) sequentially.


await


async



In your first scenario, run is the async function, and its 2 await calls to test are executed sequentially.


run


async


await


test



In your second scenario, test is the async function, and its single await operation has no effect whatsoever (since the async function has no second await operation that needs to "wait").


test


async


await


async


await



Your run function is not async, so it just runs the two functions. async/await is just an alternate syntax for promises, so your second example is equivalent to this:


run


async


await


function test(msg) {
const promise = new Promise(accept => {
console.log('in promise ', msg);
setTimeout(() => {
console.log('in timeout ', msg);
accept();
}, 1000)
});
return promise.then(() => undefined);
}

function run() {
test('a');
test('B');
}

run();



To see clearly what happens you need to put another console.log('end') at the end of your code (after run();):


console.log('end')


run();


in promise a
end
in timeout a
in promise b
in timeout b


in promise a
in promise B
end
in timeout a
in timeout B



await pauses the execution of the current function until the promise is resolved.


await



In the first example test('a') is executed but then run() is paused until the promise returned by test('a') resolves, causing console.log('end') to be executed.


test('a')


run()


test('a')


console.log('end')



In the second example test('a') is partially executed, but is paused until the promise is resolved, so test('b') is executed next, which is also paused, but then run() is finished so console.log('end') can be executed.


test('a')


test('b')


run()


console.log('end')



Hope this explanation helps!





In the fist example, end should be last line in the log, no? edit: Ah, console.log('end') is literally the last line, not inside run I guess.
– Felix Kling
Jul 2 at 23:55



end


console.log('end')


run





You're right, I didn't want to copy/paste the code, it would make my answer very long
– Rodrigo Ferreira
Jul 2 at 23:59



These two code blocks are identical:



with await


await test('a');
test('B');



with chaining


test('a')
.then(() => {
test('B');
});



All you're doing with the await is awaiting for the promise to resolve to move on. async/await is just syntactic sugar to avoid all the nesting with multiple promises


await


async


await





I think this is too vague. "test('B'); doesn't wait for test('a'); to complete before it starts" But you are also saying that await "pauses" execution.
– Felix Kling
Jul 2 at 23:54


await





@FelixKling In the second example, B doesn't wait for a to complete because await is not used
– Chris Deacy
Jul 2 at 23:57


B


a


await





I understand that. I'm just saying that "you're basically "pausing" execution of your function until that promise resolves." can be misinterpreted to "pause" all execution.
– Felix Kling
Jul 3 at 0:04





@FelixKling I can see where it could have been confusing. Updated it to be a bit more illustrative of my point
– Chris Deacy
Jul 3 at 0:16





Nice! Thank you!
– Felix Kling
Jul 3 at 0:16






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

jQyn6bm8XpnlUvmfGU1NGUVUu31L6ZtVjOYkqZLC2M3YUZ,Rej 3Z
m zZ,UEOJjWwflQudALkPo VA yUn,Q,G7qvc gY jtXT aYg8vhh1K,lQdPf5oQsCP,jaYW,ebaEE76Q,yoEDtjqsgDunvTDmeFANc,Ic

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications