Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

preface

I wanted to write a promise note several days ago, but I only knew that it was used to solve the problem of callback hell, without a detailed understanding. Therefore, I made a brief introduction of the use of several methods under its name during the study of these days.

Promise: Here’s my manual!

I: what may say is not too complete, contain more ~

Let’s take a look at it

What is promise? Is it a class? An object? An array?

Let’s print it and have a look:

console.dir(Promise);
Copy the code

That’s it. Let’s get to know it properly.

Promise is a constructor, an asynchronous programming solution proposed by ES6 to solve callback hell. As you can see from the print, it has methods like Reject, All, resolve, and its prototype has methods like catch, then, and so on.

Another expression comes from the Internet: promise, which means you will get results over a period of time. Promise has three states: pending, fulfiled and Rejected. Once the state is changed, it will not change.

// Run fn1. If a>10, run fn2. If a == 11, run fn3

function fn1(a, fn2) {
	if (a > 10 && typeof fn2 == 'function') {
	    fn2(a,function(){
	    	if(a == 11) {console.log('this is fn3')
	    	}
	    })
	}
}
fn1(11.function(a, fn3) {
    console.log('this is fn2')
    fn3()
})

Copy the code

It says that Promise is addressing callback hell, so what is callback hell? As you can see from this code, the code becomes very cumbersome after constantly nesting callback functions. The situation where there are too many nested callback functions is called callback hell.

How to use Promise

var p = new Promise(function(resolve, reject){
    // Do some asynchronous operations
    setTimeout(function(){
        console.log('Execution completed');
        resolve('Write anything.');
    }, 3000);
});
Copy the code

The Promise constructor accepts a function that takes two arguments:

  • Resolve: Callback function after asynchronous operation is successfully executed
  • Reject: Callback function when an asynchronous operation fails

then

Remember that very nested example I wrote above? Ah, don’t remember, then you read ~

The advantage of promises is that you can continue writing the Promise object in the THEN method and return it, and then continue calling the THEN for callback operations.

Therefore, from the surface, Promise can only simplify the writing method of layer upon layer callback, but in essence, the essence of Promise is state, and the callback function can be invoked in time by maintaining state and transferring state, which is much simpler and more flexible than passing callback function. So the correct scenario for using promises looks like this:

function fn1(a){
    var p = new Promise(function(resolve, reject){
        // Do some asynchronous operations
       	resolve(a);
    });
    return p;            
}
fn1(11)
.then(function(a){
	return new Promise(function(resolve, reject){
		if(a > 10) {console.log('a more than 10')
   		}
   		resolve(a);
	})
})
.then(function (a){
	if(a == 11) {console.log('a is equal to 11')}})Copy the code

I rewrote that one up there. The last one that did not return is that I did not continue then.

That’s just the chain notation. Then is equivalent to our previous callback.

The then method not only returns the promise object, but also returns data:

function fn1(a){
    var p = new Promise(function(resolve, reject){
        // Do some asynchronous operations
       	resolve(a);
    });
    return p;            
}
fn1(11)
.then(function(a){
		if(a > 10) {console.log('a more than 10')}return a
})
.then(function (a){
	if(a == 11) {console.log('a is equal to 11')}})Copy the code

reject

Change the state of the promise from Pending to Rejected, and then we can perform the failed callback in then. Here’s an example:

function fn1(a){
    var p = new Promise(function(resolve, reject){
       	if(a>10){
       		resolve(a);
       	}else{ reject(a); }});return p;            
}
fn1(9)
.then((a) = > {
	console.log('a more than 10')},(err) = > {
	console.log('a less than 10')})Copy the code

Then can accept two arguments, corresponding to a callback of resolve and reject, so we can get two results by adjusting the value of a passed in.

So a is greater than 10 and A is less than 10

catch

For those of you familiar with other languages, catch is used to grab an exception, and in promise it works just like the second argument to then, which corresponds to a callback to reject

It is written like this:

.then((a) = > {
	console.log('a more than 10')
}).catch((err) = > {
	console.log('a less than 10')})Copy the code

The effect is the same as in the second argument to then.

But it also serves another purpose: if an exception is thrown when the resolve callback (the first argument in then above) is executed, the process is not stuck, but instead is thrown into the catch method.

It’s like a try catch

Let’s look at this code again

function fn1(a){
    var p = new Promise(function(resolve, reject){
        // Do some asynchronous operations
       	resolve(a);
    });
    return p;            
}
fn1(11)
.then(function(a){
		if(a > 10) {console.log('a more than 10')}return b
})
.catch(function (err){
	console.log('Error :' + err)
})
Copy the code

In this code, the result of returning A is written as B. Normally, the browser will report an error and will not proceed. After we use catch,

The browser will print a greater than 10 and an error has occurred :ReferenceError: B is not defined.

This means that even if something goes wrong, it still goes into the catch method and passes the cause of the error to the err parameter, allowing the program to continue executing.

all

The ALL method provides the ability to perform asynchronous operations in parallel with multiple tasks, and not execute callbacks until all asynchronous operations are complete.

  • The all method takes an array of parameters, each of which is a Promise object
let p = Promise.all([fn1, fn2, fn3])

p.then(funciton(){
  // If all three are successful, they are successful
}, function(){
  // If there is only one failure, there is a failure
})
Copy the code

With all, we can perform multiple asynchronous operations in parallel. A good scenario is to open a web page, need to load various resources, all load, then initialize the page.

race

The effect of the all method is actually to run the callback based on who’s running the slowest, and then there’s another method that runs the callback based on who’s running the fastest, and that’s the race method.

Take fN123 as an example. If they are executed in 1, 2, and 3 seconds respectively, fN1 results will be output at the end of the first second, fn2 and FN3 results will be output at 2 and 3 seconds respectively.

What is the use of this race? There are many scenarios, such as using Race to set a timeout for an asynchronous request and perform the corresponding operation after the timeout.

For example, we use race to call a delay request (say 3 seconds) and an image request. At 3 seconds, if the request is successful, resolve will enter then, and if it fails, catch will enter to output an image resource request failure error.

The last

Eleven holiday is over, school people have to continue to have classes, harm.

Point a favor, work hard to progress it