Explain three asynchronous ways of JavaScript
Preface
JavaScript is a single-threaded language, but there are also some asynchronous operations, such as timers, browser events, callbacks and so on. There's also a familiar romise. Since ES6 came out, it has provided a richer way of asynchronization. For example, async function, Generator function. Today I'll share the three asynchronous uses and differences.
Before we begin to explain the usage of these three asynchronous functions, we use a case to understand what asynchrony and synchronization are.
asynchronous
setTimeout(function (res) { console.log(res) },3000,"I print in three seconds.") setTimeout(function (res) { console.log(res) },2000,"I print in 2 seconds.") setTimeout(function (res) { console.log(res) },1000,"I print in a second.")
The printing results are as follows:
As we all know, setTimeout is an asynchronous function. One of the characteristics of asynchronous function is that it can be executed as soon as it arrives. It's the same name as Promise, which means commitment. That is, when the commitment is implemented, it will be implemented. So the above printing order should be "I print after 1 second", "I print after 2 seconds" and "I print after 3 seconds" according to the time of the timer.
Synchronization (using callbacks to synchronize asynchronization)
So here comes the question.... What if I want the above asynchronous execution sequence to be synchronous? The order of printing is "I print after 3 seconds", "I print after 2 seconds" and "I print after 1 second".
Before the Promise, async, and Generator functions come out, our approach is to use callback functions.
function beSync() { setTimeout(function (res) { console.log(res); setTimeout(function (res) { console.log(res); setTimeout(function (res) { console.log(res) },1000,"I print in a second.") },2000,"I print in 2 seconds.") },3000,"I print in three seconds.") } beSync();
The printing results are as follows:
Analytical callback
We achieved synchronization through callbacks. The above code has the following problems.
- Callback inner layer nesting, code redundancy;
- There are so many callbacks that some of them can't be distinguished. That parameter comes from the callback of that function.
Based on the above analysis, Promise function, async function and Generator function came into being. Let's learn these three functions and use them to solve the above problems.
Promise function
- usage
var promise = new Promise(function(reslove,reject){ if(){ //Successful asynchronous function reslove(res)//Parameters obtained by res for the success of asynchronous functions }else{ //Asynchronous function failure reject(err) } })
- Example
var promise = new Promise(function(reslove,reject){ setTimeout(function(res){ reslove(res) },1000,'Success') }); promise.then(function(res){ console.log(res);//'Success' })
- Solve the above cases
var promise = new Promise(function (resolve) { setTimeout(function (res) { resolve(res) },3000,"I print in three seconds.") }) promise .then(function (res) { console.log(res);//"I print in three seconds." return new Promise(function (resolve) { setTimeout(function (res) { resolve(res) },2000,"I print in 2 seconds.") }) }) .then(function (res) { console.log(res);//"I print in 2 seconds." return new Promise(function (resolve) { setTimeout(function (res) { resolve(res) },1000,"I print in a second.") }) .then(function (res) { console.log(res);//"I print in a second." }) })
The printing results are as follows:
Although the amount of code mentioned above does not seem to decrease, the structure of the code looks very clear. Each parameter in the then is the result object returned asynchronously from the previous one.
Generator function
-
usage
Generator function has two distinct characteristics: one is that there is a * sign between function and function name, and the other is that the function uses the yield expression to define different internal states.
The yield means abort, while the next method means open execution, and the return status value is the result of the expression after yield.
The Generator function returns a traversal object. -
Example
function * hello() { yield '1'; yield '2'; return 'end' } var text = hello(); console.log(text.next()); console.log(text.next()); console.log(text.next());
The printing results are as follows:
- Solve the above cases
function* helloWorld() { yield setTimeout(function (res) { console.log(res) },3000,'I print in three seconds.'); yield setTimeout(function (res) { console.log(res) },2000,'I print in 2 seconds.'); yield setTimeout(function (res) { console.log(res) },1000,'I print in a second.'); }; var hw = helloWorld(); hw.next();//I print in three seconds.
3. async function
-
usage
The async function is the grammatical sugar of the Generator function. It only changes the * in the Generator function into async, and the yield into await, which has more semantics.
The async function is executed directly without the need to go through next.
The async function returns a promise object, and you can use the then method to add a callback function. -
Example
async function func() { return 'hello'; } func().then(function (res) { console.log(res)//'hello' })
- Solve the above cases
async function helloWorld() { await (function () { return new Promise(function (resolve) { setTimeout(function (res) { console.log(res); resolve(res) }, 3000, 'I print in three seconds.'); }) })(); await (function () { return new Promise(function (resolve) { setTimeout(function (res) { console.log(res); resolve(res) }, 2000, 'I print in 2 seconds.'); }) })(); await (function () { return new Promise(function (resolve) { setTimeout(function (res) { console.log(res); resolve(res) }, 1000, 'I print in a second.'); }) })(); }; helloWorld()
The printing results are as follows: