Reputation: 137
So I do know that async function returns a pending promise as soon as it hits the await keyword and if there's no await keyword used, the promise that async function returns will be resolved to the value that we return from our async function like this:
async function f() {
let p = await (new Promise(r => {
setTimeout(r, 2000, 100)
}))
return p;
}
let p = f();
console.log(p); // pending, because its awaiting.
2nd Example:
async function f() {
let p = 'someValue';
return p;
}
let p = f();
console.log(p); // {<fulfilled>: "someValue"}
2nd example also makes perfect sense, we're returning 'someValue' which as MDN says is wrapped in Promise.resolve('someValue') and that's what that's returned.
Now, what this code prints confuses me so much, it logs a pending promise!
(I know I'm not using await here and that's intentional)
async function f() {
let p = new Promise(r => r(113));
return p;
}
let af = f();
console.log(af)
We are creating a promise inside our async f function that's resolved immediately and that's the promise I return in my default created promise of async function so why does that log pending?
And even though its pending, when I expand that object, I see this at the same time:
[[PromiseResult]]: 113
Could anyone please help?
Upvotes: 1
Views: 702
Reputation: 21120
This probably happens because the JavaScript engine needs to "flatten" the returned promise.
console.log(Promise.resolve(113)); //=> fulfilled
const a = async () => 113;
console.log(a()); //=> fulfilled
const b = async () => Promise.resolve(113);
console.log(b()); //=> pending
The last scenario logs a pending promise. This is probably because the JavaScript engine sees that you return a promise from an async function. In this scenario, when you await b()
, you expect 113
as a result. An async function always returns a promise. If the resolved value (return value of an async function) of this promise is another promise then the promise is "flattened".
To better demonstrate the point, imagine the return value of b
as (Firefox console notation):
Promise { <state>: "pending", <value>: Promse { <state>: "fulfilled", <value>: 123 } }
Whereas the return value of both the first code block and a
is:
Promse { <state>: "fulfilled", <value>: 123 }
The flattening of nested promises is done by the engine and probably added to end of the event loop and thus ran after the current running context. Which means that the outer promise is pending until that happens.
This behaviour might be engine dependant, so I would not rely on this behaviour. A Promise
instance is a promise of an eventual value and should be treated as such. Never expect a promise to resolve immediately. If you expect a fulfilled promise you are better of using a normal synchronous function, which avoids the use of promises.
Upvotes: 2