Asynchronous programming practices of when. js under node. js, node. jswhen. js
Assume a business scenario:
Get and save the rss feed to a file through the rss address, and save the rss address to the file.
To complete the business in this scenario, you need to complete three tasks:
1. Read the rss address from the file.
2. Get rss.
3. Save it to a file.
Finally, the three tasks are integrated.
Preparation:
Save the RSS address file address.txt.
Http://programmer.csdn.net/rss_programmer.html
Task 1:
Read the content of the rss address file and return it through callback.
Copy codeThe Code is as follows:
Var getRssAddress = function (path, callback ){
Fs. readFile (path, {encoding: 'utf8'}, function (err, data ){
Callback (err, data );
});
}
Task 2:
Get to rss through the rss address and return an error or data through callback.
Copy codeThe Code is as follows:
Var getRss = function (url, callback ){
Var data = '';
Http. get (url, function (res ){
Res. on ('data', function (chrunk ){
Data + = chrunk;
});
Res. on ('end', function (){
Callback (null, data );
});
}). On ('error', function (err ){
Callback (err, null );
});
}
Task 3:
Save rss to a file and return an error through callback.
Copy codeThe Code is as follows:
Var saveRss = function (data, callback ){
Fs.writeFile('rss.txt ', data, 'utf8', function (err ){
Callback (err );
});
}
Integration:
Copy codeThe Code is as follows:
Getrssaddress('ssss.txt ', function (err, data ){
If (err ){
Console. log (err );
Return;
}
GetRss (data, function (err, data ){
If (err ){
Console. log (err );
Return;
}
SaveRss (data, function (err ){
If (err) console. log (err );
});
});
});
The above Code is fully asynchronous, and the most common callback is used to process the return of asynchronous logic. The advantage is that standard writing is easy for everyone to accept. The disadvantage is that the coupling is too strong and handling exceptions is troublesome, the code is not intuitive, especially in scenarios where the business logic is complex and the processing tasks are large. The layers of callback will make people look at it and make it difficult to maintain the code.
One of the implementations of Promise/A specifications, when. js, is targeted at such problem domains.
Let's take a look at the transformed code.
Task 1:
Copy codeThe Code is as follows:
Var getRssAddress = function (path ){
Var deferred = when. defer ();
Fs. readFile (path, {encoding: 'utf8'}, function (err, data ){
If (err) deferred. reject (err );
Deferred. resolve (data );
});
Return deferred. promise;
}
Task 2:
Copy codeThe Code is as follows:
Var getRss = function (url ){
Var deferred = when. defer ();
Var data = '';
Http. get (url, function (res ){
Res. on ('data', function (chrunk ){
Data + = chrunk;
});
Res. on ('end', function (){
Deferred. resolve (data );
});
}). On ('error', function (err ){
Deferred. reject (err );
});
Return deferred. promise;
}
Task 3:
Copy codeThe Code is as follows:
Var saveRss = function (data ){
Var deferred = when. defer ();
Fs.writeFile('rss.txt ', data, 'utf8', function (err ){
If (err) deferred. reject (err );
Deferred. resolve ();
});
Return deferred. promise;
}
Integration:
Copy codeThe Code is as follows:
Getrssaddress('ssss.txt ')
. Then (getRss)
. Then (saveRss)
. Catch (function (err ){
Console. log (err );
});
Explanation:
The "Deferred/promise" model defined by Promise/A is the "Publish/subscriber" model. Releasing an event through the Deferred object can be A resolve event or A failed reject event; use the Promise object to subscribe to the subscription that has been completed or failed.
In the Promises/A specification, each task has three states: default (pending), complete (fulfilled), and rejected ).
1. The default status can be transferred to the completion status in one way. This process is called resolve, and the corresponding method is deferred. resolve (promiseOrValue );
2. The default status can also be changed to the failed status. This process is called reject, and the corresponding method is deferred. reject (reason );
3. By default, you can also use deferred. Y (update) to declare the task execution information, such as the execution progress;
4. Status transfer is one-time. Once the task is changed from initial pending to another status, it enters the execution process of the next task.
Follow the above Code.
Define a deferred object through when. defer.
Var deferred = when. defer ();
After the asynchronous data is obtained successfully, a complete event is published.
Deferred. resolve (data );
After an asynchronous data acquisition failure occurs, a failure event is published.
Deferred. reject (err );
The Promise object is returned for subscription.
Return deferred. promise;
Subscription is the subscription of completion/failure/notification through the then method of the Promise object.
Getrssaddress('ssss.txt ')
. Then (getRss)
Then has three parameters: onFulfilled, onRejected, and onProgress.
Promise. then (onFulfilled, onRejected, onProgress)
If the previous task is resolve (data), the onFulfilled function is triggered and data is used as its parameter.
If the previous task is reject (reason), onRejected will be triggered and the reason will be received.
At any time, either onFulfilled or onRejected can be triggered only once.
For Exception Handling, when. js also provides extremely convenient methods. then can deliver errors. when multiple tasks are executed in serial mode, we can define onRejected only in the last then. You can also call the catch function after the last then to catch exceptions of any task.
This method is simple and clear.
Copy codeThe Code is as follows:
Getrssaddress('ssss.txt ')
. Then (getRss)
. Then (saveRss)
. Catch (function (err ){
Console. log (err );
});
Promise brings great convenience to asynchronous programming, so that we can focus on the implementation of a single task without getting into the pyramid. The above code is only basic use, when. the functions provided by js are far more than those mentioned in this Article. For details, refer to the official API.