In the process of writing Node.js, continuous IO operations may lead to a "pyramid nightmare". Multiple nesting of callback functions makes the code difficult to maintain. Use CommonJs's Promise to encapsulate asynchronous functions and use a unified chain. API to get rid of the nightmare of multiple callbacks.
The non-blocking IO model provided by Node.js allows us to use callback functions to handle IO operations. However, when continuous IO operations are required, your callback functions will be nested multiple times, making the code very unsightly and difficult to maintain. And there may be a lot of duplicate code for error handling, the so-called "Pyramid of Doom".
What is Promise?
There are many Promise specifications of CommonJs. We generally discuss the Promise/A specification, which defines the basic behavior of Promise.
A Promise is an object that usually 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. Represents incomplete, successful completion and operation failure respectively. Once the state of the 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 manipulate the value returned after possible success in the future or the reason for failure. The then method looks like this:
promise.then(onFulfilled, onRejected)
Obviously, the then method accepts two parameters, which are usually two functions. One is used to handle the results after the operation succeeds, and the other is used to handle the reasons after the operation fails. The first of these two functions The two parameters are the result after success and the reason for failure respectively. If the parameter passed to the then method is not a function, this parameter will be ignored.
The return value of the then method is a Promise object. This feature allows us to chain call then to achieve the effect of controlling the flow. There are many detailed issues here, such as value transfer or error handling. The specification of Promise is defined as follows:
The return value of the onFulfilled or onRejected function is not a Promise object, then this value will be used as the first parameter of onFulfilled in the next then method. If the return value is a Promise object, why is the return value of the then method the Promise object?
If an exception is thrown in the onFulfilled or onRejected function, the status of the Promise object returned by the then method will be changed to Rejected. If the Promise object calls then, the Error object will be used as the first parameter of the onRejected function
If the Promise status becomes Fulfilled and no onFulfilled function is provided in the then method, the Promise object status returned by the then method becomes Fulfilled and the successful result is the result of the previous Promise. The same is true for Rejected.
In addition, onFulfilled and onRejected are executed asynchronously.
Standard implementation: q
The above is the specification of Promise, and what we need is its implementation. q is a library with better implementation specifications for Promise/A.
First we need to create a Promise object. The specifications for the creation of Promise objects are in Promise/B. I will not give a detailed explanation here, just go to the code.
Most implementations of Promise are similar in the creation of Promise. By creating a defer object with a promise attribute, if the value is successfully obtained, defer.resolve(value) is called. If it fails, defer.reject(reason) is called. Finally, return the promise attribute of defer. This process can be understood as calling defer.resolve to change the Promise's status to Fulfilled, and calling defer.reject to change the Promise's status to Rejected.
When faced with a series of continuous asynchronous methods, how to use Promise to write beautiful code? Take a look at the example below.
It seems good, the code is more maintainable and beautiful, so what if you want concurrency?
Conclusion
This article mainly introduces the use of 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 pointed out 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 has more advantages when encapsulating functions with asynchronous methods.Okay, this article ends here, I hope it can be helpful to everyone.