An asynchronous function
- Asynchronous functions, also known as async/await(syntax keyword), are the application of ES6Promise to JS functions. This feature enhances JS both in behavior and syntax, allowing code written synchronously to be executed asynchronously
Example 1: This interval resolves to a value after a timeout, and if the value is accessed by other code in the program, a resolution handler is needed
let p = new Promise((resolve, reject) = >
setTimeout(resolve, 1000.3));
p.then((x) = > console.log(x)); / / 3
Copy the code
async
- Async keyword is used to declare an asynchronous function, the key can be used in a function declaration, the function expression of the arrow on the functions and methods, this keyword can make function has the characteristics of asynchronous, but overall code still worth is synchronous, in terms of parameter and closures, asynchronous function still has the common JS function normal behavior
async function foo() {
console.log(1);
return 3;
} // Add a resolution handler to the returned schedule
foo().then(console.log);
console.log(4); console.log(5); // 1,4,5, 3 Copy the code
Conclusion: If an asynchronous function returns a value using return, the value is wrapped in promise.resolve () as a contract. An asynchronous function always returns a contract object
- The return value of the asynchronous function expects an object of the Thenable interface, which can be provided to the then () handler to unpackage. If not, the result is considered resolved
// Return an object that does not implement the thenable interface
async function bar() {
return ['bar'];
}
bar().then(console.log); // ['bar']
// Return a non-periodic object that implements the thenable interface async function baz() { const thenable = { then(callback) { callback('baz'); } }; return thenable; } baz().then(console.log); // baz // Return a date async function qux() { return Promise.resolve('qux'); } qux().then(console.log); // qux Copy the code
Conclusion: the return value of the asynchronous function, which contains thenable, provides then handler unpacking, otherwise returns the value as the result of processing, but note that the error of rejecting the date will not be caught by the asynchronous function
async function foo() {
console.log(1);
Promise.reject(3);
}
// Attach a rejected handler to the returned promise
foo().catch(console.log); console.log(2); / / 1 / / 2 // Uncaught (in promise): 3 Copy the code
await
- Since asynchronous functions are mainly for tasks that will not be completed immediately, there is a need for the ability to pause and resume execution. With await, you can pause the code execution of the asynchronous function. The waiting period is resolved
// Asynchronous writing
let p = new Promise((resolve, reject) = >
setTimeout(resolve, 1000.3));
p.then((x) = > console.log(x)); / / 3
/ / async written
async function foo() { let p = new Promise((resolve, reject) = > setTimeout(resolve, 1000.3)); console.log(await p); } Copy the code
Summary: The await keyword pauses the code following the async function, allowing the JS runtime thread to execute. This behavior is similar to the yield keyword in generators. “The await keyword also attempts to unpackage the value of the object, pass the value to the expression, and asynchronously resume the execution of the async function.”
Let’s look at an example involving stopping and resuming execution: this is a very interesting example, although you don’t see the effect now, it helps you understand await more bluntly
-
To understand this example better, you need to know these questions first
-
Wait for the return value and continue with the other thread
-
The same await is placed from the top down
-
When the await has multiple processes, it is executed in a multi-column order
Example 1:
-
async function foo() {
console.log(await Promise.resolve('foo'));
}
async function bar() {
console.log(await 'bar');
} async function baz() { console.log('baz'); } foo(); bar(); baz(); // baz // bar // foo Copy the code
Summary: Normally this is the order, “but when you run the browser, the resulting bar and foo values will switch places”,
First, let’s talk about the implementation principle:
- When foo() is called, foo adds two columns of processes to the message queue, the first column waiting for the returned value, and the second column executing the process after it gets the returned value,
- Then go to bar () and add a process to the first column of the message queue. Then execute baz and print out ‘baz’.
- Then start the process of message queue, foo (column 1) obtains the result and returns the value, and then continue the process of message queue (column 1) of bar, at this time print ‘bar’, at this time the process of message queue (column 1) has been executed.
- Go to the second column, foo executes the process with the value returned by the process in the first column, prints foo,
Next, let’s talk about why this is not the case for the browser: 1TC39 made a change to how it handles cases where await is followed by an await. Await promise.resolve (‘ foo ‘) in foo () in this example will only generate an asynchronous task. So it doesn’t have two columns, it only has one column, so it will be in await order
- With that in mind, let’s look at the final example
async function foo() {
console.log(2);
console.log(await Promise.resolve(8));
console.log(9);
}
async function bar() { console.log(4); console.log(await 6); console.log(7); } console.log(1); foo(); console.log(3); bar(); console.log(5); // 1 // 2 // 3 // 4 // 5 //8 // 9 // 6// 7 Copy the code
Summary: The latest modified result shown above, according to the original result process should be
- Print 1, run foo, print 2, add two columns to the message queue, print 3, run bar, print 4, add one column to the message queue, print 5, start executing the first line of the message queue, Foo gets the return value, bar prints 6, then prints 7, go back to foo, second column, print 8, print 9
This article was typeset using MDNICE