the code snippet likes below:
console.log('test')
async function async1() {
console.log('before wait');
await wait();
console.log('after wait');
}
async function wait() {
try {
return await new Promise((res, rej) => {
console.log('wait');
rej('reject');
});
} catch (reason) {
console.log(reason);
}
}
async function test() {
async1();
console.log('before resolve');
await Promise.resolve();
console.log('after resolve');
}
test();
console.log('test end');
you can also run the code in playground
actual result:
[LOG]: "test"
[LOG]: "before wait"
[LOG]: "wait"
[LOG]: "before resolve"
[LOG]: "test end"
[LOG]: "reject"
[LOG]: "after resolve"
[LOG]: "after wait"
I thought after wait
would be printed first, since it is pushed in the micro task queue early?
where am I wrong?
I took advice from @Seblor
It may become clearer if you replace the async/await with the then function.
then I removed all the async/await
console.log('test')
function async1() {
console.log('before wait');
return wait().then(() => {
console.log('after wait');
})
}
function wait() {
return new Promise((res, rej) => {
console.log('wait');
rej('reject');
}).catch((reason) => {
console.log(reason);
})
}
function test() {
async1();
console.log('before resolve');
Promise.resolve().then(() => {
console.log('after resolve');
})
}
test();
console.log('test end');
Then I realized the first code pushed in micro task queue is the code in catch
, followed by console.log('after resolve')
, finally console.log('after wait')
Okay I had a hard time spotting it but I think I get it.
So we all agree where the issue is, the problem you see is that the promise rejection is executed before the promise that resolves, but the 'after resolve' is printed before 'after wait'.
The thing is that even though there are 2 promises, there are 3 micro tasks here. The first one is the return await new Promise(
, the second one is await Promise.resolve()
, and the 3rd one is the awaiting of the call to the function: await wait()
.
The call to wait()
returns a promise, which you await
, creating a new microtask that is queued AFTER await Promise.resolve()
.
So the rejecting promise finished, printing 'reject', then the resolving promise finished, printing 'resolve', and finally the returned promise from wait()
is awaited, printing 'after wait'.
It may become clearer if you replace the async/await with the then
function. So this:
async function async1() {
console.log('before wait');
await wait();
console.log('after wait');
}
Would be written like this:
function async1() {
console.log('before wait');
return wait().then(() => {
console.log('after wait');
});
}
So in order of execution (of the micro tasks only):
await new Promise((res, rej) => {
registers the 1st Promiseawait Promise.resolve()
registers the 2nd Promisethen
callback, creating the 3rd microtask.