This article mainly introduces the elegant Processing Method of Nodejs asynchronous callback. This article uses the new features in ES6 and uses a very elegant method to solve the callback problem. For more information, see
Preface
The biggest highlight of Nodejs is its event-driven, non-blocking I/O model, which makes Nodejs highly concurrent processing capability and is very suitable for compiling network applications. In Nodejs, most of the I/O operations are asynchronous, that is, the results of I/O operations must be basically processed in the callback function, for example, the following function reads the file content:
The Code is as follows:
Fs. readFile ('/etc/passwd', function (err, data ){
If (err) throw err;
Console. log (data );
});
What should we do if we read two files and combine the contents of these two files? Most people who are new to js may do this:
The Code is as follows:
Fs. readFile ('/etc/passwd', function (err, data ){
If (err) throw err;
Fs. readFile ('/etc/passwd2', function (err, data2 ){
If (err) throw err;
// Process data and data2 data here
});
});
If we deal with multiple similar scenarios, isn't the callback function layer by layer nested ah, this is the common say of the callback pyramid or callback hell (http://callbackhell.com/) problem, it is also the biggest headache for JavaScript code.
This layer-by-layer nested Code brings many problems to the development, mainly reflected in:
1. Less likely code
2. Difficult debugging
3. It is difficult to troubleshoot exceptions
This article describes how to handle the above asynchronous callback elegantly.
Preliminary solution: asynchronous callback through recursive Processing
We can use recursion as the code execution control tool. Encapsulate the operations to be executed into a function and control the Code Execution Process through recursive calls in the callback function:
The Code is as follows:
Var fs = require ('fs ');
// List of files to be processed
Var files = ['file1', 'file2', 'file3'];
Function parseFile (){
If (files. length = 0 ){
Return;
}
Var file = files. shift ();
Fs. readFile (file, function (err, data ){
// Process file data here
ParseFile (); // after processing, process the next file through recursive calling.
});
}
// Start processing
ParseFile ();
The above code is used to process files in the array in sequence as an example to introduce how to control the Code Execution Process by recursion.
It is good to use it in some simple scenarios. For example, we can save the data in an array to the database in sequence.
The recursive method can solve some simple asynchronous callback problems. However, it seems powerless to process complicated asynchronous callbacks (for example, to synchronize the results of multiple asynchronous operations ).
Gorgeous: asynchronous callback processing using third-party libraries such as Async, Q, and Promise
To better handle nested callback, you can consider using some third parties to handle asynchronous libraries. Of course, you can write an auxiliary tool for asynchronous processing on your own.
Commonly used asynchronous databases include async, q, and promise. From the npmjs.org website, async is the most popular. I have used async before, and it is indeed quite convenient, and the control flow of various asynchronous processing is also quite well implemented.
We use async to process the code that initially reads two files at the same time. The example is as follows:
The Code is as follows:
Var async = require ('async ')
, Fs = require ('fs ');
Async. parallel ([
Function (callback ){
Fs. readFile ('/etc/passwd', function (err, data ){
If (err) callback (err );
Callback (null, data );
});
},
Function (callback ){
Fs. readFile ('/etc/passwd2', function (err, data2 ){
If (err) callback (err );
Callback (null, data2 );
});
}
],
Function (err, results ){
// Process data and data2 data here. The content of each file is obtained from results.
});
Through the async module, the asynchronous execution process can be well controlled, which solves the issue of layer-by-layer callback. The code is clearer than before, but it is still inseparable from the callback function.
It would be nice to think about asynchronous processing without using callback functions. Next, let's talk about the new features of ES6 to achieve this goal.
Elegance: embraces ES6 and replaces callback functions to solve callback hell Problems
In other words, EcmaScript Harmony (ES6) has introduced many new features to js. If you are not familiar with ES6, You Can Baidu.
To use the new features of ES6 in nodejs, you must use v0.11.x or later.
This article describes how to use the Generator feature to replace callback functions. Do you know nothing about Generator? Let's take a look.
The co and thunkify modules are used here. You can install them using the npm install command.
Take the problem mentioned in the beginning as an example. The example code using the generator feature is as follows:
The Code is as follows:
Var fs = require ('fs ')
, Co = require ('co ')
, Thunkify = require ('thunkify ');
Var readFile = thunkify (fs. readFile );
Co (function *(){
Var test1 = yield readFile('test1.txt ');
Var test2 = yield readFile('test2.txt ');
Var test = test1.toString () + test2.toString ();
Console. log (test );
})();
It is also very easy to handle exceptions in the code, just like this:
The Code is as follows:
Try {
Var test1 = yield readFile('test1.txt ');
} Catch (e ){
// Handle exceptions here
}
Is this code much more elegant? Is it nice to process Asynchronization like writing Synchronous Code!
In the nodejs field for Web development, the most popular framework is express. It is worth mentioning that the core member of express, corner stone, leads a new Web framework-koa, koa claims to be the next-generation Web development framework. With the feature of ES6 generator, koa avoids calling back layers when developing Web systems.
Summary
Reference one sentence promoted by the fibjs project: Less Callback, More Girls-Less Callback, More sisters