Use Promise in NodeJS to encapsulate asynchronous functions _ node. js

Source: Internet
Author: User
This article describes how to use Promise in Node. js to encapsulate asynchronous functions and use unified chained APIs to get rid of the nightmare of multiple callbacks. it is a very practical little skill, I hope my friends will like writing Node. during the js process, continuous IO operations may lead to "pyramid nightmare". the multiple nesting of callback functions makes it difficult to maintain the code. the Promise of CommonJs is used to encapsulate asynchronous functions, use a unified chained API to get rid of the nightmare of multiple callbacks.

Node. the non-blocking I/O model provided by js allows us to use callback functions to process IO operations. However, when consecutive I/O operations are required, your callback functions are nested in multiple layers, and the code is not beautiful, it is not easy to maintain, and there may be a lot of repetitive code for error handling, that is, the so-called "Pyramid of Doom ".

The code is as follows:


Step 1 (function (value1 ){
Step 2 (value1, function (value2 ){
Step 3 (value2, function (value3 ){
Step 4 (value3, function (value4 ){
// Do something with value4
});
});
});
});


This is actually a Node. javaScript Control flow has many solutions for this problem, such as using async or eventProxy. However, the topic of this article is to use Promise in the CommonJs specification to solve this problem.

What is Promise?

There are many Promise specifications in CommonJs. we generally discuss the Promise/A + specification, which defines the basic behavior of Promise.

Promise is an object that generally represents an asynchronous operation that may be completed in the future. This operation may succeed or fail, so a Promise object generally has three states: Pending, Fulfilled, and Rejected. Incomplete, successful, and failed. Once the state of a Promise object changes from Pending to Fulfilled or Rejected, its state cannot be changed.

A Promise object usually has a then method, which allows us to operate on the value returned after the future may be successful or the cause of failure. The then method is like this:

Promise. then (onFulfilled, onRejected)
Obviously, the then method accepts two parameters. they are usually two functions, one for processing the result after the operation is successful, and the other for processing the cause after the operation fails, the first parameters of these two functions are the result of success and the cause of failure. If not a function is passed to the then method, this parameter is ignored.

The return value of the then method is a Promise object. This feature allows us to call then in a chain to control the flow. There are many details, such as value transfer or error handling. The Promise specification is defined as follows:

If the returned value of the onFulfilled or onRejected function is not a Promise object, the value will be used as the first parameter of onFulfilled in the next then method. if the returned value is a Promise object, the return value of the then method is the Promise object.
If an exception is thrown in the onFulfilled or onRejected function, the state of the Promise object returned by the then method is converted to Rejected. if the Promise object calls then, the Error object is used as the first parameter of the onRejected function.
If the Promise state changes to Fulfilled, but the onFulfilled function is not provided in the then method, the state of the Promise object returned by the then method changes to Fulfilled and the successful result is the result of the previous Promise. The same is true for the Rejected.
In addition, both onFulfilled and onRejected are executed asynchronously.

Standard implementation: q

The above is the Promise specification, and what we need is its implementation. q is A library that has A better implementation specification for Promise/A +.

First, we need to create a Promise object. the specifications for Promise object creation are in Promise/B. here we will not explain in detail and directly go to the code.

The code is as follows:


Function (flag ){
Var defer = q. defer ();
Fs. readFile ("a.txt", function (err, data ){
If (err) defer. reject (err );
Else defer. resolve (data );
});
Return defer. promise;
}

Most Promise implementations are similar in Promise creation. by creating a defer object with the promise attribute, if the value is obtained successfully, defer is called. resolve (value). if it fails, defer is called. reject (reason), and finally return the promise attribute of defer. This process can be understood as calling defer. resolve to change the Promise status to Fulfilled, and calling defer. reject to change the Promise status to Rejected.

In the face of a series of continuous asynchronous methods, how can we use Promise to write beautiful code? See the following example.

The code is as follows:


Promise0.then (function (result ){
// Dosomething
Return result;
}). Then (function (result ){
// Dosomething
Return promise1;
}). Then (function (result ){
// Dosomething
}). Catch (function (ex ){
Console. log (ex );
}). Finally (function (){
Console. log ("final ");
});

In the above code, the then method only accepts OnFulfilled, while the catch method is actually then (null, OnRejected). In this way, as long as a series of asynchronous methods are always returned successfully, the code runs down in a waterfall manner. if any of the asynchronous methods fails or an exception occurs, the function in the catch will be executed according to the Promise specification of CommonJs. Q also provides the finally method, which is literally easy to understand, that is, whether resolve or reject, the finally function will be executed in the end.

It looks good, and the code is more maintained and beautiful. what if I want concurrency?

The code is as follows:


Q. all ([promise0, promise1, promise2]). spread (function (val0, val1, val2 ){
Console. log (arguments );
}). Then (function (){
Console. log ("done ");
}). Catch (function (err ){
Console. log (err );
});

Q also provides APIs for concurrency. by calling the all method and passing a Promise array, you can continue to use then's chained style. For example, q. nfbind can convert the Native API of Node. js into Promise to unify the code format. More APIs are not described here.

Conclusion

This article describes how to use Promise to solve Node. js control flow problems, but Promise can also be applied to the front-end. EMCAScript6 has provided Native API support. It should be noted that Promise is not the only solution. async is also a good choice and provides a more friendly concurrency control API, however, I think Promise is more advantageous in encapsulating functions with asynchronous methods.

Well, this article is here first, hoping to help you.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.