Objective
A Promise object can be understood as an action to be performed (often used for asynchronous operations), and a Promise object can be used to organize code in a chained way, making the code more intuitive. And because Promise.all such a method exists, it makes it easy to perform multiple operations at the same time.
The rise of promise is due to the fact that callback functions are often inter-related in asynchronous method invocations. This situation led to the emergence of a callback pyramid problem. Not only is the code hard to write, but it's also difficult to understand when the problem is complicated.
Examples are as follows:
Db.save (data, function (data) {
//do something ...
Db.save (data1, function (data) {
//do something ...
Db.save (data2, function (data) {
//do something ...
Done (DATA3); Return Data
})
});
Suppose you have a database save operation that requires three times of data to be saved in three tables at a time. So our code is similar to the code above. What happens when the second db.save
problem is assumed? Based on this consideration, we also need to use logic like this in each of the callback layers try...catch
. This is the source of all evils and the point at which node is beginning to be widely criticized.
Another disadvantage is that, assuming there is no dependency between our three saves, we still need to wait for the previous function to finish before we can perform the next step, instead of three to save the parallel, and then return a three saved result after the save. (or to implement it requires skill)
Unfortunately, when I first started touching node, I wrote a lot of these hell.
Later, because or write the front-end code more, I contacted the ES6, found a solution to the abyss of the sharp weapon promise.
In fact, early in ES6 promise before, Q,when.js,bluebird and so on Promise standard (reference promise/a+) built their own promise wheels.
(Read an article, I think it makes sense.) Inside said, do not extend the built-in native objects. This approach is not geared towards the future. So here's a hint: be cautious when using a library that extends native promise. )
Here only the promise of the native are discussed.
ES6 Promise
Promise Object State
Before we explain promise, let's start with some theories:
The promise/a+ specification stipulates that the Promise object is a finite state machine.
Of it three states:
1. pending
(in execution)
2. fulfilled
(Success)
3. reject
(Refusal)
This is the pending
initial state, and the ending state fulfilled
rejected
(the end state indicates that the promise life cycle has ended).
The state transition relationship is:
Pending->fulfilled,pending->rejected.
Various events, such as execution of success events, execution failure events, and so on, will be triggered as the state transitions.
Promise Form
Promise's looks are like this:
var promise = new Promise (function func (resolve, Reject) {
//do somthing, maybe async
if (success) {return
res Olve (data);
} else {return
reject (data);
}
});
Promise.then (function (data) {
//do something ... e.g
console.log (data);
}, Function (err) {
// Deal the Err.
})
The variable promise here is an instance of the Promise object.
The Promise object executes logic in the function when it is created func
.
When the logic is finished and there is no error, resolve
the callback passes the value to a particular place. Where is this special place? The then in the following code, we use then
the callback function in to process resolve
the result. For example, in the above code, we will simply output the value to the console. If there is an error, the reject
then
error is processed in the second callback function to.
In conjunction with the theory of the finite state machine above, we know that when the callback function code is executed in the Promise constructor, the state is followed by the state, pending
resolve
fulfilled
reject
after which the state isreject
Promise Data Flow
The above is the first data flow situation of promise.
More funny, the Promise method is then
still able to return a promise object so that we can then
do the same with the next one.
The then
two callback functions in the first one determine then
what kind of promise object the first one returns.
Assuming that the first then
callback does not return a Promise object, the second then
caller is still the original promise object, except that its resolve value becomes the return value of the first callback function in the first then.
Assuming that the first then
callback function returns a Promise object, the second then
caller becomes the new promise object, and the second then
Wait for the new Promise object resolve or reject to execute the callback.
Although it was a bit of a spare, but I feel that I am still very clear. haha ~
If an error is encountered anywhere, the error is then referred to the first callback function that is encountered with the second callback function then
. It can be understood that errors are always backwards reject
until they are processed.
In addition, the Promise object also has a method catch
that accepts a callback function to handle the error.
That
Promise.catch (function (err) {
//deal the Err.
})
Assuming that the processing of errors is similar, this method can centralize the processing of errors. So the other then methods don't need a second callback.
Promise of concurrency control
Promise has a "static method"-- Promise.all
(note that it is not promise.prototype), which accepts an element as an array of promise objects.
This method also returns a Promise object, and if all the promise objects in the array are all resolve
, the resolve
values will be used as an array as the Promise.all
value of the return value of the method (the Promise object), which resolve
can then
then be method is processed. If any of the promise in the array is reject
, the reject
value is the Promise.all
value of the method's return value reject
.
The one thing that's really op:
then
The order in which the first callback function of the method receives resolve
(as described above, an array) is consistent with the order of the Promise.all
array of parameters in, rather than chronological order.
There is also a Promise.all
similar method Promise.race
, which also receives an array, except that it accepts only resolve
the first value.
Turn other objects into promise objects
Promise.resovle
method, you can return a promise object that is not a promise object as a parameter.
There are two kinds of situations:
Assuming that the incoming parameter does not have a .then
method, the returned Promise object becomes a resolve
state, and its resolve
value is the object itself.
Assuming that the incoming parameter comes with a then
method (called an thenable
object), the type of the object becomes promise and its then
method becomes a Promise.prototype.then
method.
Promise is the solution to the asynchronous solution?
Finally, it is important to say that the role of promise is to solve the problem of the callback pyramid, which does not actually play a significant role in controlling the asynchronous process. The real use of promise to control the asynchronous process, we also need to use the ES6 generator
function. (for example, TJ Great God's Co Library implementation).
However, ES7 will have a more brilliant solution: The async/await
scheme is similar to co, but it adds native support. Let's wait and see.
Summarize
The above is about JavaScript ES6 Zhongyuan promise All content, I hope the content of this article for everyone to learn ES6 can help. If you have questions, you can exchange messages.