preface
Before the koala program ape Nick shared some of the use of Node in the actual work, we went through the node memory model of the mountain, and over the Node concurrency model of the mountain, the following will enter the Node asynchronous programming environment, welcome to discuss!
The ultimate solution for asynchrony
In 2017, Node 7.6 finally supports Async/Await. Async functions are syntactic candy for Generator functions and are the ultimate solution for ASYNCHRONOUS JS programming.
It can be considered that:
Async function == CO + generator function
Async has the following advantages over CO:
- Better semantics: async and await are clearer than asterisks and yield. Async means that there is an asynchronous operation in a function, and await means that the following expression needs to wait for the result;
- Wider applicability: The CO library convention is that yield can only be followed by Thunk or Promise objects, while async can be followed by await and Promise objects and primitive values (numeric, string, and Boolean, but this is equivalent to synchronous operations).
Before this, the asynchronous programming of JS has gone through the evolution of Callback, Promise, Generator and Async. Next, we will go through the asynchronous development process.
The Callback function Callback
In JS, asynchronous programming is done through Callback, which takes one function as an argument to another asynchronous function and is used to process asynchronous results. An example:
Something.save(function(err) {
if (err) {
//error handling
return; // No return value} console.log('success');
});
Copy the code
The challenges of overusing callbacks:
- If you don’t organize your code properly, it’s very easy to create callback hell, which makes your code hard to understand.
- It’s easy to leave out error handling code;
- You cannot return a value using a return statement, and you cannot use the throw keyword.
It is for these reasons that the JavaScript world is always looking for feasible solutions that make asynchronous JavaScript development easier.
One possible solution is the Async module. If you’ve spent a lot of time with callbacks, you’ll probably get a good sense of how complicated it is to use asynchronous functions in JavaScript if you want something to be executed in parallel, or sequentially, or even using asynchronous functions to map elements in an array. So, thanks to Caolan McMahon for writing the Async module to solve these problems.
Using the Async module, you can easily write code like this:
async.map([1, 2, 3], AsyncSquaringLibrary.square,
function(err, result){
// result will be [1, 4, 9]
});
Copy the code
The Async module provided some convenience, but it was still not simple enough and the code was not easy to read, hence the Promise.
Promise function
Make a Promise
Something.save()
.then(function() {
console.log('success');
})
.catch(function() {
//error handling
})
Copy the code
The then and catch registered callback functions handle the next step and exception handling, respectively. This has the advantage of being able to chain operations:
saveSomething()
.then(updateOtherthing)
.then(deleteStuff)
.then(logResults);
Copy the code
This is just another way of writing the callback function, so instead of loading the callback horizontally, we’re going to load it vertically.
The Generator function
Generator functions are an ES6 implementation of coroutines, and are not syntactic sugar.
In the first step, coroutine A is executed;
In the second step, the execution of coroutine A is suspended halfway, and the execution authority is transferred to coroutine B.
Third, coroutine B returns execution authority (after some time);
Step 4, coroutine A resumes execution.
function* gen(x){
var y = yield x + 2;
return y;
}
Copy the code
The above code is a Generator function. It is different from ordinary functions and can be paused, so the function name is preceded by an asterisk to indicate the difference.
The whole Generator function is a encapsulated asynchronous task, or a container for asynchronous tasks. Where asynchronous operations need to be paused, use the yield statement. The Generator function is executed as follows.
var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }
Copy the code
The Generator function can pause and resume execution, which is the fundamental reason it encapsulates asynchronous tasks. In addition, it has two features that make it a complete solution for asynchronous programming: data exchange and error handling inside and outside functions.
-
Data exchange: g.ext (data);
-
Error handling: g.row (‘ error ‘);
The biggest problem with the Generator is that you have to manually call next() to perform the next step, hence the auto-executor CO.
Co actuators
Co function library
var co = require('co');
co(gen);
Copy the code
Generator automatic execution requires a mechanism that automatically cedes execution rights when an asynchronous operation has a result. There are two ways to do this.
(1) Callback function. Wrap asynchronous operations as Thunk functions that give back execution rights in callback functions. (2) Promise objects. Wrap the asynchronous operation as a Promise object and hand back execution with the then method.
The specific implementation of the CO function is shown in the end reference article, which will not be repeated here.
Read more: Asynchronous programming in other languages
C # is async await keyword for asynchronous calls, thread internal implementation based on www.cnblogs.com/jesse2013/p…
The Java Spring framework has the @async annotation for asynchronous calls, and the internal implementation is based on threads spring.io/guides/gs/a…
Refer to the article
- Explain the evolution of asynchronous JavaScript functions in detail
- The meaning and usage of async functions
- The meaning and usage of Generator functions
- The meaning and usage of co function library