转载:await - JavaScript | MDN
The await operator is used to wait for a Promise and get its fulfillment value. It can only be used inside an async function or a JavaScript module.
# Syntax
1 | await expression; |
# Parameters
-
expressionA
Promiseor any value to wait for.
# Return value
The fulfillment value of the promise, or the expression itself’s value itself if it’s not a Promise .
# Exceptions
Throws the rejection reason if the promise is rejected.
# Description
The await expression causes async function execution to pause until a promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment. When resumed, the value of the await expression is that of the fulfilled promise.
The expression is resolved in the same way as Promise.resolve() , which means thenable objects are supported, and if expression is not a promise, it’s implicitly wrapped in a Promise and then resolved.
If the promise is rejected, the await expression throws the rejected value. The function containing the await expression will appear in the stack trace of the error. Otherwise, if the rejected promise is not awaited or is immediately returned, the caller function will not appear in the stack trace.
An await splits execution flow, allowing the caller of the async function to resume execution. After the await defers the continuation of the async function, execution of subsequent statements ensues. If this await is the last expression executed by its function, execution continues by returning to the function’s caller a pending Promise for completion of the await 's function and resuming execution of that caller.
Because await is only valid inside async functions and modules, which themselves are asynchronous and return promises, the await expression never blocks the main thread and only defers execution of code that actually depends on the result, i.e. anything after the await expression.
# Examples
# Awaiting a promise to be fulfilled
If a Promise is passed to an await expression, it waits for the Promise to be fulfilled and returns the fulfilled value.
1 | function resolveAfter2Seconds(x) { |
# Thenable objects
Thenable objects will be fulfilled just the same.
1 | async function f2() { |
# Conversion to promise
If the value is not a Promise , it converts the value to a resolved Promise , and waits for it.
1 | async function f3() { |
# Promise rejection
If the Promise is rejected, the rejected value is thrown.
1 | async function f4() { |
# Handling rejected promises
You can handle rejected promises without a try block by chaining a catch() handler before awaiting the promise.
1 | const response = await promisedFunction().catch((err) => { |
# Top level await
You can use the await keyword on its own (outside of an async function) within a JavaScript module. This means modules, with child modules that use await , wait for the child module to execute before they themselves run, all while not blocking other child modules from loading.
Here is an example of a simple module using the Fetch API and specifying await within the export statement. Any modules that include this will wait for the fetch to resolve before running any code.
1 | // fetch request |
# Control flow effects of await
When an await is encountered in code (either in an async function or in a module), execution of all code following this is immediately paused and pushed into the microtask queue. The main thread is then freed for the next task in the event loop. This happens even if the awaited value is an already-resolved promise or not a promise. For example, consider the following code:
1 | async function foo(name) { |
In this case, the two async functions are synchronous in effect, because they don’t contain any await expression. The three statements happen in the same tick. In promise terms, the function corresponds to:
1 | function foo(name) { |
However, as soon as there’s one await , the function becomes asynchronous, and execution of following statements is deferred to the next tick.
1 | async function foo(name) { |
This corresponds to:
1 | function foo(name) { |
While the extra then() handler is not necessary and can be merged with the previous one, its existence means the code will take one extra tick to complete. The same happens for await . Therefore, make sure to use await only when necessary (to unwrap promises into their values).
# Improving stack trace
Sometimes, the await is omitted when a promise is directly returned from an async function.
1 | async function noAwait() { |
However, consider the case where someAsyncTask asynchronously throws an error.
1 | async function lastAsyncTask() { |
Only lastAsyncTask appears in the stack trace, because the promise is rejected after it has already been returned from noAwait — in some sense, the promise is unrelated to noAwait . To improve the stack trace, you can use await to unwrap the promise, so that the exception gets thrown into the current function. The exception will then be immediately wrapped into a new rejected promise, but during error creation, the caller will appear in the stack trace.
1 | async function lastAsyncTask() { |
However, there’s a little performance penalty coming with return await because the promise has to be unwrapped and wrapped again.
# Comments
1 | const getLastPost = async () => { |
-
promise.then
1
2
3
4
5const lastPost = getLastPost().then((post) => console.log(post));
console.log("end");
// end
// {title: 'at nam consequatur ea labore ea harum'} -
async wrap IIFE(Immediately Invoked Function Expression)
1
2
3
4
5
6
7
8(async () => {
const lastPost = await getLastPost();
console.log(lastPost);
})();
console.log("end");
// end
// {title: 'at nam consequatur ea labore ea harum'} -
top level await
1
2
3
4
5
6const lastPost = await getLastPost();
console.log(lastPost);
console.log("end");
// {title: 'at nam consequatur ea labore ea harum'}
// endImport in HTML need by module way.
1
<script type="module" defer src="script.js"></script>