When I was a little white, I read a lot of documents about Promise. I never understood what the pain point of asynchronous operation means
It wasn't until I turned to all the Chinese documents on the first page of Google that I had an epiphany. In fact, it was the simplest and rudest to understand from his English literal meaning
This is a promise, which is equivalent to providing a way in the code of what to do after the promise at any time. This promise may or may not be fulfilled, of course, it may also be in the process of fulfillment
Using this instead of the callback function we used to write can avoid callback hell in JavaScript programs
So don't learn the grammar first. Understand it from another way. I hope it can help you better learn or get started
What is Promise?
Promise is a solution for asynchronous programming, which can replace traditional solutions, such as callback functions and events
It unifies its usage in ES6 and provides a native Promise object, which represents the final completion (or failure) of asynchronous operation and its result value
As an object, Promise has the following two characteristics:
- The state of the object is not affected by the outside world
- Only the result of asynchronous operation can determine the current state, and no other operation can change this state,
This is also the origin of the name Promise. Its English meaning is commitment, which means that other means cannot be changed
- Only the result of asynchronous operation can determine the current state, and no other operation can change this state,
- Once the state changes, it will not change, that is, Promise has only one state at any time
- pending: initial status, not success or failure status;
Fully (resolved): the operation is successfully completed;
rejected: operation failed status - There are only two possibilities for the state of the Promise object to change: from Pending to Resolved and from Pending to Rejected,
As long as these two situations occur, the state will solidify, will not change again, and will maintain this result all the time,
Even if the change has occurred, you will get this result immediately if you add a callback function to the Promise object,
This is completely different from events. The characteristic of events is that if you miss it and listen again, you won't get results
- pending: initial status, not success or failure status;
Creation and use of Promise
- The constructor accepts a function called executor, which takes two f function parameters, resolve and reject.
new Promise( /* executor */ function(resolve, reject { ... }) );
- Promise is usually used to block code and asynchronous operations, including file calls, API calls, DB calls, IO calls, and so on
- The startup of these asynchronous operations occurs in the execution function. If the asynchronous operation is successful, the creator of promise calls the resolve() function to return the expected results,
Similarly, if an unexpected error occurs, the specific error information is passed by calling the reject() function - Since promise will be executed immediately, we cannot check the initial state of promise, so the easiest way to create a promise that takes time to execute is
Using the setTimeOut() function, you can visually see the state and its change process through the output of the browser console
var promiseFir = new Promise(function(resolve, reject) { setTimeout(function() { resolve({ message: 'It's fun to share knowledge with you!', code: 200 }); }, 2000) }) console.log(promiseFir); setTimeout(function() { console.log(promiseFir); }, 2000)
Promise method
- Three prototype methods
- Promise.prototype.then(onFulfilled, onRejected) chain operation
- Promise.prototype.catch(onRejected) catch errors
- Promise. Prototype. Finally (onfinantly) final operation
- Let's use a small example to briefly and quickly understand the usage of the three prototype methods
// Take a short story as an example. You are a school child. You ask your mother for a phone call. She said: I want to buy a mobile phone at the end of this month var momsPromise = new Promise(function(resolve, reject) { momsSavings = 20000; // Because mom doesn't have enough savings, she can't buy gifts // momsSavings = 200000; // If mother has enough savings, she can buy gifts priceOfPhone = 60000; if (momsSavings > priceOfPhone) { resolve({ brand: "iphone", model: "6s" }); } else { reject("We don't have enough savings. Let's save more money."); } }); momsPromise.then(function(value) { console.log("Wow, I got this phone as a gift ", JSON.stringify(value)); }); momsPromise.catch(function(reason) { console.log("Mom can't buy me a phone because ", reason); }); momsPromise.finally(function() { console.log( "Whether my mother can buy me a phone or not, I still love her" ); });
- 4 static methods
Promise.prototype.then(onFulfilled, onRejected) chain operation
- The Promise.prototype.then() method returns a new Promise object, so it can be written in chain
- Promise.prototype.then() method has the following three parameters: success callback, failure callback and forward callback. Generally, only the first one needs to be implemented, followed by optional ones
function ptFir() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log('Method 1 execution'); resolve('Method 1 completed'); }, 2000) }) } function ptSec() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log('Method 2 execution'); resolve('Method 2 completed'); }, 1000) }) } function ptThi() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log('Method 3 execution'); resolve('Method 3 completed'); }, 3000) }) } ptFir().then(function(data) { console.log('First callback:' + data); return ptSec(); }).then(function(data) { console.log('Second callback:' + data); return ptThi(); }).then(function(data) { console.log('Third callback:' + data); return 'Not yet? It's over!'; }).then(function(data) { console.log(data); })
Promise.prototype.catch(onRejected) catch errors
- The Promise.prototype.catch() method is an alias of Promise.prototype.then(null, rejection), which is used to specify the callback function when an error occurs
- The error of Promise object is * * "bubbling" * * and will be passed back until it is caught, that is, the error will always be caught by the next catch statement
promise().then(function(data) { // todo something }).catch(function(err) { // Error processing last callback function })
Promise. Prototype. Finally (onfinantly) final operation
Regardless of the final state of the promise object, after the callback function specified by. then or catch is executed, the callback function specified by the finally method will be executed
promise().then(function(data) { // todo something }).catch(function(err) { // Error processing last callback function }).finally(function(result) { // Actions that must be performed after processing then/catch })
Promise.resolve() / Promise.reject()
- These are help methods or shortcuts that help you easily create the resolve and reject methods
- Note: if the parameter of Promise.resolve() method,
If it is not an object with a. then() method (also known as thenable object), a new Promise object is returned and its state is fully;
If the parameter of Promise.resolve method is an instance of Promise object, it will be returned intact - The Promise.reject() method is the same as above
var promise = Promise.resolve('Helloļ¼Here is the content of successful execution!'); // var promise = Promise.reject('error, here is the discovered error! ')// Success and failure can only have one state promise.then(function(data) { console.log(data) }); promise.catch(function(err) { console.log(err) });
Promise.all()
- When dealing with multiple promises, it is best to create a promise array first, and then perform the necessary operations on these promise sets
- The Promise.all(iterable) method returns a promise instance that contains all the promises in the iterable parameter
- The callback is resolved when it is resolved or the parameter does not contain promise
- If there is a reject ed promise in the parameter, the instance callback fails. The reason for the failure is the result of the first failed promise
- ***Attention*** The asynchronous operations here are executed in parallel. They will not enter then() until they are all executed,
And the all() method will put the results of all asynchronous operations into an array and pass it to then() - The following example shows what needs to be explained
- Only when the state of the three methods becomes fully, the state of p will become fully. At this time, the return values of the three methods form an array and are passed to the callback function of p
- As long as one of the three methods is rejected, the state of p becomes rejected. At this time, the return value of the first rejected instance will be passed to the callback function of p
function ptFir() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log('Method 1 execution'); resolve('Method 1 completed'); }, 2000) }) } function ptSec() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log('Method 2 execution'); resolve('Method 2 completed'); }, 1000) }) } function ptThi() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log('Method 3 execution'); resolve('Method 3 completed'); }, 3000) }) } Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) { console.log(data); console.log({}.toString.call(data)); })
Promise.race()
- The Promise.race(iterable) method returns a promise. Once a promise in the iterator is resolved or rejected, the returned promise will be resolved or rejected
- The effect of the all() method is actually * * "Whoever runs slowly will execute the callback based on who" * *,
In contrast, there is another method * * "Whoever runs fast will execute the callback according to who". This is the race() method, which originally means race - What's the use of this race() method? There are still many usage scenarios. For example, we can use race() to set the timeout for an asynchronous request,
And execute the corresponding operation after timeout
// ptFir(), ptSec(), ptThi() ditto Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) { console.log(data); console.log({}.toString.call(data)); })
Some rules of thumb for using Promise
- Use Promise when performing asynchronous operations or using blocking code
- For the readability of the code, the resolve() method treats. Then (), and the reject () method corresponds to. catch()
- Make sure to write both. catch() and. then() methods to implement all promise
- If you need to do something in both cases, use. finally()
- We only change each promise once
- We can add multiple handlers to a promise
- The return type of all methods in the Promise object, whether static or prototype, is Promise
- In the all() method, no matter which promise is not completed first, the order of promises remains in the value variable
Reference document 1 - thoroughly understand Promise in Javascript
Reference document 2 -- popular and simple understanding of then in Promise
Reference document 3 -- Understanding Promise in Javascript
Reference document 4 -- JavaScript Promise object