Last June, ES2015 was formally released (that is, ES6,ES6 is its nickname), of which promise was formally regulated. As one of the most important features of ES6, we need to grasp and understand thoroughly. This article will be from shallow to deep, explain the basic concept of promise and how to use it.
ES6 Promise First pull out for a walkThe concept of complexity first, we first simple rough promise to use, there is an intuitive feeling. So the first question is, what is promise? is a class? Object? Array? Function? Don't guess, just print it out and see, Console.dir (Promise), it's so simple and rude. Such a look to understand, promise is a constructor, his body has all, reject, resolve these familiar methods, the prototype has then, catch and so on the same familiar method. So there must be a then and catch method for the promise new object, yes. Let's play a new game.
var New Promise (function(resolve, Reject) { // do some asynchronous operations SetTimeout ( function() { console.log (' execution complete '); Resolve (' whatever data '); (a);});
The promise constructor takes a parameter, is a function, and passes in two parameters: Resolve,reject, which represents the callback function after the successful execution of the asynchronous operation and the failed execution of the asynchronous operation. In fact, the "success" and "failure" to describe is not accurate, according to the standard, resolve is to promise the status of Fullfiled,reject is to promise the status of rejected. But at the beginning we can understand this first, and then scrutiny the concept later. In the above code, we performed an asynchronous operation, that is, after settimeout,2 seconds, the output "done" and called the Resolve method. Running the code will output "execution complete" in 2 seconds. Attention! I just new an object, and did not call it, we passed in the function has been executed, this is a need to pay attention to a detail. So when we use promise, we usually wrap it in a function, and run the function when needed, such as:
function RunAsync () { varnew Promise (function(resolve, Reject) { / / do some asynchronous operation setTimeout (function() { console.log (' execution complete '); Resolve (' whatever data '); (a); }) ; return p; } RunAsync ()
At this point you should have two questions: 1. Is packing such a function for yarn use? 2.resolve (' random data '); This is dry hair? We're going to keep speaking. At the end of our packaged function, we return the Promise object, that is, we have a promise object that executes the function. Remember the Promise object has then, catch method? This is where the power is, look at the following code:
RunAsync (). Then (function(data) { console.log (data); // You can use the data from the back to do some other things . // ......});
Call the then method directly on the return of Runasync (), then receive a parameter, be a function, and get the arguments that we call resolve simultaneous in Runasync. Running this code will output "execution complete" in 2 seconds, followed by the output "whatever data". At this point you should be able to understand that the function inside then is the same as our usual callback function, which can be executed after the completion of the Runasync asynchronous task execution. This is the role of promise, simply speaking, is able to separate the original callback, after the asynchronous operation is finished, the callback function is executed in a chained way. You might be dismissive, so what's the promise? I'm going to wrap the callback function and pass it to Runasync, like this:
function RunAsync (callback) { setTimeout (function() { console.log (' execution complete '); Callback (' whatever data '); );} RunAsync (function(data) { console.log (data);});
The effect is the same, but also hard to do with promise. So the question is, what should I do with multiple levels of callbacks? What if callback is also an asynchronous operation and needs a corresponding callback function after execution? You can never define a callback2, and then pass it on to callback. The advantage of promise is that you can continue to write the Promise object and return it in the then method, and then continue to invoke then to perform the callback operation.
use of chained operationsSo, from the surface, promise just can simplify the writing of the layer callback, but in essence, the essence of Promise is "state", with the maintenance state, the way to transfer state to make the callback function can be called in time, it is more simple and flexible than the transfer callback function. So the correct scenario for using promise is this:
runAsync1 (). Then (function(data) { console.log (data); return runAsync2 ();}). Then (thefunction(data) { console.log (data) ; return runAsync3 ();}). Then (function(data) { console.log (data);});
This enables the output of the contents of each asynchronous callback in sequence, every two seconds, and the data passed to resolve in RunAsync2, which can be obtained in the next and then method. The results of the operation are as follows: Guess RunAsync1, RUNASYNC2, runAsync3 How are the three functions defined? Yes, that's the way it is (the code is longer, please expand yourself):
functionrunAsync1 () {varp =NewPromise (function(Resolve, reject) {//do some asynchronous operationsSetTimeout (function() {Console.log (' Asynchronous Task 1 execution complete '); Resolve (' Whatever data 1 '); }, 1000); }); returnp; }functionRunAsync2 () {varp =NewPromise (function(Resolve, reject) {//do some asynchronous operationsSetTimeout (function() {Console.log (' Asynchronous Task 2 execution complete '); Resolve (' Whatever data 2 '); }, 2000); }); returnp; }functionrunAsync3 () {varp =NewPromise (function(Resolve, reject) {//do some asynchronous operationsSetTimeout (function() {Console.log (' Asynchronous task 3 execution complete '); Resolve (' Whatever data 3 '); }, 2000); }); returnp; }
View Code
In the then method, you can also return the data directly instead of the Promise object, then you can receive the data in the subsequent then, for example, we modify the above code to:
runAsync1 (). Then (function(data) { console.log (data); return runAsync2 ();}). Then (thefunction(data) { console.log (data) ; return ' Direct return to data '; // This returns the data directly . }). Then (function(data) { console.log (data);});
Then the output becomes this:
the use of RejectHere, you should have a basic understanding of what "promise is". So let's take a look at ES6 's promise. We use the resolve, but also useless reject it, what is it to do? In fact, our previous example is only a "successful" callback, there is no "failure" situation, reject's role is to put the promise state as rejected, so that we can capture in then, and then execute "failure" callback. Look at the code below.
functionGetNumber () {varp =NewPromise (function(Resolve, reject) {//do some asynchronous operationsSetTimeout (function(){ varnum = Math.ceil (math.random () *10);//generate a random number of 1-10 if(num<=5) {resolve (num); } Else{Reject (' The numbers are too big '); } }, 2000); }); returnp; }getnumber (). Then (function(data) {Console.log (' Resolved '); Console.log (data); }, function(reason, data) {Console.log (' Rejected '); Console.log (reason); });
The GetNumber function is used to asynchronously get a number, 2 seconds after execution completes, if the number is less than or equal to 5, we think is "successful", call resolve modify the state of promise. Otherwise we think it is "failed", call reject and pass a parameter as the reason for the failure. Run GetNumber and then pass two parameters, then the method can accept two parameters, the first one corresponding to the resolve callback, the second corresponding to the reject callback. So we were able to get the data they sent. Run this code multiple times and you will randomly get the following two results: or
use of CatchWe know that the Promise object has a catch method in addition to the then method, what does it do? In fact, it is the same as the second parameter of then, used to specify the callback of the reject, the usage is this:
GetNumber (). Then (function(data) { Console.log (' resolved '); Console.log (data);}). Catch (function(reason) { console.log (' rejected '); Console.log (reason);});
The effect is the same as the second parameter written in then. However, it has another function: When executing the resolve callback (that is, the first argument in the above then), if the exception is thrown (the code is wrong), then the error will not die JS, but into the catch method. Take a look at the following code:
GetNumber (). Then (function(data) { Console.log (' resolved '); Console.log (data); // somedata not defined here }). Catch (function(reason) { console.log (' rejected '); Console.log (reason);});
In Resolve's callback, we Console.log (Somedata), and somedata this variable is undefined. If we do not have to promise, the code runs here directly in the console error, not down run. But here, you get the result: it goes into the catch method, and the wrong reason is passed to the reason parameter. Even the wrong code will not get an error, which has the same function as our Try/catch statement.
usage of allThe all method of promise provides the ability to perform asynchronous operations in parallel and executes callbacks after all asynchronous operations have been performed. We still use the three functions defined above, RUNASYNC1, RunAsync2, runAsync3, to see the following example:
Promise.all ([RunAsync1 (), RunAsync2 (), runAsync3 ()]). Then (function(results) { Console.log (results);});
Executes with Promise.all, all receives an array parameter, and the value in it eventually returns the Promise object. In this way, three asynchronous operations are executed in parallel until they are all executed before they come into the then. So, where did the data returned by three asynchronous operations go? It's all in then, and all the results of all the asynchronous operations are put into an array and passed to then, which is the results above. So the output from the above code is: With all, you can execute multiple asynchronous operations in parallel, and it's cool to handle all the return data in a callback? There is a scene is very suitable for this, some of the game material more than the application, open the Web page, pre-load the need to use a variety of resource slices, flash and various static files. Once all is loaded, we will initialize the page again.
the use of raceThe effect of the all method is actually "who runs slowly, who is the quasi-callback", then there is another way "who runs fast, with whom to execute the callback", this is the race method, this word is meant to race. Race usage As with all, we change the delay of the above runAsync1 to 1 seconds to see:
Promise.race ([RunAsync1 (), RunAsync2 (), runAsync3 ()]). Then (function(results) { Console.log (results);});
These three asynchronous operations are also executed in parallel. As a result you should be able to guess that after 1 seconds the RUNASYNC1 has been executed, and then the inside is executed. The result is this: Did you guess right? Not exactly, is it. When the callback in then is executed, RUNASYNC2 () and runAsync3 () do not stop and still execute. Then after 1 seconds, they output the sign of their end. What's the use of this race? The use of the scene is still a lot, for example, we can use race to set the timeout time for an asynchronous request, and after the timeout, the corresponding operation, the code is as follows:
//Request a picture resourcefunctionrequestimg () {varp =NewPromise (function(Resolve, reject) {varIMG =NewImage (); Img.onload=function() {Resolve (IMG); } img.src= ' xxxxxx '; }); returnp;}//delay function for timing a requestfunctiontimeout () {varp =NewPromise (function(Resolve, Reject) {SetTimeout (function() {Reject (' Picture request timed out '); }, 5000); }); returnp;} Promise.race ([Requestimg (), timeout ()]). Then (function(results) {Console.log (results);}).Catch(function(reason) {console.log (reason);});
The REQUESTIMG function asynchronously requests a picture, I write the address as "xxxxxx", so it must not be successfully requested. The timeout function is an asynchronous operation with a delay of 5 seconds. We put the two functions returned to the Promise object into the race, so they will race, if the picture request is successful within 5 seconds, then go through the then method to perform the normal process. If the 5-second picture has not been successfully returned, then timeout will win, then go to catch and quote "Picture Request timed out" information. The results of the operation are as follows:
SummaryIs that what ES6 promise? Yes, that's the basic stuff you can use. How come I've seen done, finally, success, fail and so on, what are these? These are not in the promise standard, but in the grammatical sugars we implement ourselves. All of the asynchronous operations in this article take settimeout as an example, the reason why Ajax is not used is to avoid confusion, because when it comes to Ajax, many people's first reaction is jquery Ajax, and jquery has its own promise implementation. If you understand the principle, you know that using settimeout is the same as using Ajax. Speaking of jquery, I have to spit out a groove, jquery promise to achieve too much rubbish, all kinds of grammatical sugar to people, I think the reason why promise is not universal and jquery has a great relationship. We'll talk about jquery in the back. About promise also some content is need to speak, confined to space, this article only for ES6 promise explanation, next will have plain English explanation series:
- promise/a+ specification
- The Promise in jquery
Please look forward to!
Plain English Explanation promise (I.)