According to MDN Web Docs, "await" is used to "wait for a Promise", but the expression following the keyword can also be "any value to wait for", hence not necessarily a Promise.
In the below demo the awaited value is a call to a void function, i.e. a function that implicitly returns "undefined". Note: the called function does not return a Promise. What exactly does it mean to await a void function call?
Demo: Add keyword "await" to the beginning of line 11, and see how it changes logging from "FC" to "CF".
"use strict";
function pr() {
return Promise.resolve(null);
}
function invokeAsyncOperation(cb) {
pr().finally(cb);
}
async function main() {
try {
// demo: await the following statement
invokeAsyncOperation(() => console.log("C"));
} catch (e) {} finally {
console.log("F");
}
}
main();
You're seeing the result of two things:
From the docs you linked:
If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
Loosely speaking,¹ await x where x is not a promise is the same as await Promise.resolve(x). So when you use await, there's always a promise involved.
Promise completion handlers are always called asynchronously, x and await x have different timing: The former is synchronous; the latter is asynchronous:
x.await puts a completion handler on the promise.console.log.You see the log for C before the log for F because the completion handler logging C is already in the microtask queue before the completion handler for F is added, so it gets run first.
¹ Actually, Promise.resolve is always involved, even when x is already a promise. But the extra promise gets optimized away if x is already a native promise (of the same concrete class). You can see the resolve operation in Step 2 of the algorithm for await.