A better solution to JavaScript experience Asynchronization: javascript Asynchronization
I. History of asynchronous Solutions
Asynchronous JavaScript operations have been a headache, so many people are constantly proposing various solutions. It can be traced back to the earliest callback function (old ajax friends), Promise (not new friends), and ES6 Generator (strong friends ).
We may have used a well-known Async a few years ago. js, but it does not get rid of the callback function, and the error handling is also based on the Convention "the first parameter of the callback function is used to pass errors. The well-known callback hell is still a prominent issue until the Generator changes This asynchronous style.
However, with the emergence of async await in ES7 (a new friend of bunker), we can easily write Synchronous Code and have an asynchronous mechanism. It can be said that it is currently the simplest and most elegant, the best solution.
Ii. async await syntax
Async await syntax is relatively simple and can be considered as the syntax sugar of Generator, which is more semantic than asterisks and yield. The following simple example shows how to output hello world in 1 second:
function timeout(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); });}async function asyncPrint(value, ms) { await timeout(ms); console.log(value)}asyncPrint('hello world', 1000);
Await can only be used in the async function. If it is used in a common function, an error is returned.
Await is followed by a Promise object (of course, other values can also be packaged into a Promise for immediate resolve, which makes no sense)
Await will wait until the result of Promise is returned and continue execution
Await waits for a Promise object, but does not need to write. then (). You can directly get the returned value, fine-tune the code above, and find that the returned result can also output hello world:
function timeout(ms) { return new Promise((resolve) => { setTimeout(_ => {resolve('hello world')}, ms); });}async function asyncPrint(ms) { let result = await timeout(ms); console.log(result)}asyncPrint(1000);
Iii. async await error handling
As mentioned above, await waits for a Promise object but does not need to be written. then. catch (). You can catch errors directly by using try catch, which can avoid redundant and cumbersome error handling code. You can also fine-tune the above example:
Function timeout (MS) {return new Promise (resolve, reject) =>{ setTimeout (_ => {reject ('error')}, MS ); // reject simulate error, Return error});} async function asyncPrint (MS) {try {console. log ('start'); await timeout (MS); // error console returned here. log ('end'); // so this code will not be executed} catch (err) {console. log (err); // The error is caught here.} asyncPrint (1000 );
If multiple await instances exist, they can be put together in try catch:
async function main() { try { const async1 = await firstAsync(); const async2 = await secondAsync(); const async3 = await thirdAsync(); } catch (err) { console.error(err); }}
4. Notes on async await
1) As mentioned earlier, the running result of the Promise object after the await command may be a reject or a logic error, so it is best to put await in the try catch code block.
2) asynchronous operations of multiple await commands. If there is no dependency, trigger them at the same time.
const async1 = await firstAsync();const async2 = await secondAsync();
In the above Code, if async1 and async2 are two independent asynchronous operations, the write will be time-consuming, because only after firstAsync is completed will secondAsync be executed, and Promise can be fully used. all elegantly handled:
let [async1, async2] = await Promise.all([firstAsync(), secondAsync()]);
3). await can only be used in the async function. If it is used in a common function, an error is returned:
Async function main () {let docs = [{}, {}, {}]; // error await is only valid in async function docs. forEach (function (doc) {await post (doc); console. log ('main') ;});} function post () {return new Promise (resolve) =>{ setTimeout (resolve, 1000 );});}
Add async to the forEach internal method:
async function main() { let docs = [{}, {}, {}]; docs.forEach(async function (doc) { await post(doc); console.log('main'); });}function post(){ return new Promise((resolve) => { setTimeout(resolve, 1000); });}
However, you will find that the three main columns are output at the same time, which means that post is executed concurrently, rather than the secondary execution. changing it to for can solve the problem, the three main columns are output in 1 second respectively:
async function main() { let docs = [{}, {}, {}]; for (let doc of docs) { await post(doc); console.log('main'); }}function post(){ return new Promise((resolve) => { setTimeout(resolve, 1000); });}
In short, after the async await is used, the whole person is refreshed, and various fancy asynchronous operations can be implemented with very concise and elegant code. In the case of complicated business logic, there is no need to fall into callback hell. I dare not say that this must be the ultimate solution, but it is indeed the most elegant solution at present!