Promise is a solution to asynchronous programming
Before we learn about promise, let’s look at what asynchrony is.

The first thing to remember is that JS is a single-threaded language, which means it can’t be executed concurrently by multiple threads like the JAVA language.

So let’s talk about synchronization. Synchronization refers to the execution of code line by line, and the code below must wait for the execution of the code above to complete. When encountering some time-consuming tasks, such as network requests, it is easy to block and must wait for data requests to come in before performing subsequent operations. So asynchronous execution is the ability to request data while still performing subsequent tasks.

In real life, for example, you have to cook and cook. If it’s synchronous, you have to wait for the food to finish cooking before you can cook it, or you have to cook the food before you can cook it, which obviously takes a lot of time. If it is done asynchronously, you can hand over the cooking task to the cooker, and then cook the food. After cooking the food, take the food out. This process can be called an asynchronous operation.

The fetch operation is equivalent to executing a callback function (a function that executes asynchronously is a callback function, because it will eventually be called to the main thread), and I have briefly explained synchronous and asynchronous execution and callback functions.

Look again if you don’t understand, or look at the parsing performed asynchronously here.

Impact of asynchronous tasks?

So we can see that asynchronous execution depends on the callback function, so what is the effect of the callback function in asynchronous operation? That’s callback hell.

Callback hell refers to the layers of nested callback functions that are nested within each other.

Let’s take a look at the following example, where you need to print 3 Hello after 1s, 3 vue.js after 1 second and 3 Node.js after 1 second

The first thing you need to know is that setTimeout is an asynchronous operation, where the first argument passed in is the callback function, which will be executed at the specified time.

setTimeout(() = > {
  console.log("hello");
  console.log("hello");
  console.log("hello");
  setTimeout(() = > {
    console.log("vue.js");
    console.log("vue.js");
    console.log("vue.js");
    setTimeout(() = > {
      console.log("node.js");
      console.log("node.js");
      console.log("node.js");
    }, 1000);
  }, 1000);
}, 1000);
Copy the code
Use Promise to fix callback hell

The code above creates callback hell, which can be very complicated when there is too much code. Here’s an elegant way to address these issues: Promise

I’m not going to go into the details of how Promise is used here, but you can look at the code in the comments below.

Promise() is called automatically. The Promise parentheses accept a function as an argument. Resolve, reject
Resolve and reject are not fixed, of course, but we usually write them this way for semantics to make them easier to understand
new Promise((resolve, reject) = > {// Resolve indicates the callback if the asynchronous operation succeeds. Reject means a callback in the event of failure (not yet).
  setTimeout(() = > {
    resolve();	// Since resolve and reject are functions, we call them in parentheses
  }, 1000);
}).then(() = > {
  Then, once resolve() is executed, then() is executed
  // All subsequent callbacks can be handled in the then() function, which makes the code clearer
  console.log("hello");
  console.log("hello");
  console.log("hello");
  setTimeout(() = > {
    console.log("vue.js");
    console.log("vue.js");
    console.log("vue.js");
    setTimeout(() = > {
      console.log("node.js");
      console.log("node.js");
      console.log("node.js");
    }, 1000);
  }, 1000);
})
Copy the code

If we return a Promise instance in the then() method, then returning a Promise will continue to use the then() method to resolve the nesting, forming a chain call. So how do you do that? As follows:

new Promise((resolve, reject) = > {
  // The function executed on the first callback
  setTimeout(() = > {
    resolve();
  }, 1000);
}).then(() = > {
  // The code handled by the first callback function
  console.log("hello");
  console.log("hello");
  console.log("hello");
  return new Promise((resolve, reject) = > {
    // The function executed by the second callback
    setTimeout(() = > {
      resolve();
    }, 1000);
  })
}).then(() = > {
  // The code processed by the second callback function
  console.log("vue.js");
  console.log("vue.js");
  console.log("vue.js");
  setTimeout(() = > {
    console.log("node.js");
    console.log("node.js");
    console.log("node.js");
  }, 1000);
})
// Finally there is a layer of nesting so you can decide.
Copy the code

The code is more complex, but the logic is clearer. Even with more layers of nesting, the code is still clean. You must use the Promise wrap for any nested callback function like the one above (such as a network request).

For another example, incrementing the value by one every 1s, printing the result of incrementing by one, passing the result to the next callback, incrementing by one and printing it twice.

new Promise(resolve= > {Since I'm not going to call reject, this parameter can be omitted
  setTimeout(() = > {
    resolve(0);Arguments passed in resolve are received in then
  }, 1000)
}).then(data= > {
  data++;
  console.log(data);/ / 1
  return new Promise(resolve= > {
    setTimeout(() = > {
      resolve(data);
    }, 1000)
  })
}).then(data= > {
  data++;
  console.log(data);/ / 2
})
Copy the code

If you look closely at setTimeout(), you’ll see that there’s only one line of code in there, and that the increment and output operations are all executed in then(). That’s the idea of Promise, putting all the code that needs to be executed in the callback into then() and then calling resolve(). This might still be a bit of a hassle, but the amount of code in the actual code for callbacks is quite large, and it’s much clearer to use this structure.

With that said, let’s say reject(). The comment says reject() is a call when a callback fails, so if we write code into then() when a callback fails, then Promise() doesn’t seem very elegant, because then has both successful and failed callback codes.

Promise takes this into account, of course, so our callback code when we fail is in catch(), which means “catch,” and once you call reject() you’re in the catch() method.

Here’s a simple example:

new Promise((resolve, reject) = > {
  setTimeout(() = > {
      let num = Math.floor(Math.random() * 11);// Random number from 0 to 10
  	  if (num >= 5) {
  	    resolve(num);
  	  } else{ reject(num); }},1000)
}).then(data= > {
  console.log("Successfully executed callback with value:"+data);
}).catch(reason= > {
  console.log("Failed callback executed with value:"+reason);
})
Copy the code

Asynchronously obtain a random number (0-10), execute 1 second later. Call resolve() to modify the Promimse state; otherwise, call reject() to modify the Promise state. Parameters in Reject () can be considered as the cause of failure, so reason is generally used as the parameter name.

So now you’re confused about what a Promise state is?

Promise has three states: pending/depressing/Rejected;
  • Pending: Pending state, in which a Promise is pending before the callback function of an asynchronous task executes, such as a network request or timer time
  • This is a big pity: The fulfilled state. When we invoke the resolve() method, the promise state will change from pending to fulfilled, and the then() method will be invoked
  • Rejected: The reject state. When we call reject(), the promise state changes from pending to Rejected and the Catch () method is called
Failed callback code can also be written in then(). That’s right. Let’s see another way to write Promise.

Again, take the code above as an example.

new Promise((resolve, reject) = > {
  setTimeout(() = > {
      let num = Math.floor(Math.random() * 11);// Random number from 0 to 10
  	  if (num >= 5) {
  	    resolve(num);
  	  } else{ reject(num); }},1000)
}).then(data= > {
  console.log("Successfully executed callback with value:"+data);
},reason= > {
  console.log("Failed callback executed with value:"+reason);
})
Copy the code

There are two arguments to then(). The first argument is the callback code used to handle success, and the second argument is the callback code used to handle failure.

Chain calls and abbreviations for Promise

Look at the following code:

new Promise(resolve= > {
  // This is called after 1s to execute the code in then()
  setTimeout(() = > {
    resolve('aaa');
  }, 1000)
}).then(data= > {
  console.log(data);//aaa
  return new Promise(resolve= > {
    resolve(data + 'bbb');
  })
}).then(data= > {
  console.log(data);//aaabbb
  return new Promise(resolve= > {
    resolve(data + 'ccc');
  })
}).then(data= > {
  console.log(data);//aaabbbccc
})
Copy the code

As you can see, the code above does not perform asynchronous operations in the later THEN, so there is no need to use Promise to wrap code that does not perform asynchronous operations.

new Promise(resolve= > {
  setTimeout(() = > {
    resolve('aaa');
  }, 1000)
}).then(data= > {
  console.log(data);
  return Promise.resolve(data + 'bbb');
}).then(data= > {
  console.log(data);
  return Promise.resolve(data + 'ccc');
}).then(data= > {
  console.log(data);
})
Copy the code

Here’s an even easier way to do it:

new Promise(resolve= > {
  setTimeout(() = > {
    resolve('aaa');
  }, 1000)
}).then(data= > {
  console.log(data);
  return data + 'bbb';
}).then(data= > {
  console.log(data);
  return data + 'ccc';
}).then(data= > {
  console.log(data);
})
Copy the code

Returns the result directly, actually internally encapsulates the returned result.

For the above operations, we will certainly not only have successful callbacks, but also unsuccessful ones.

new Promise(resolve= > {
  setTimeout(() = > {
    resolve('aaa');
  }, 1000)
}).then(data= > {
  console.log(data);
  // The short for failure
  return Promise.reject('error info');
  // Of course, if we throw an exception, we also execute the code in the catch
  //throw 'error info';
}).then(data= > {
  console.log(data);
  return Promise.resolve(data + 'ccc');
}).then(data= > {
  console.log(data);
}).catch(reason= > {
    If the catch() callback fails, then() is not executed
  console.log('Failed callback performed',reason);
})
Copy the code
Promise. All () method

Promise.all() is primarily used to handle multiple asynchronous tasks at the same time. When we need to complete a business, that is, when both network requests are successful, we execute the code in the callback function. Use promise.all () at this point. Here I use setTimeout() to simulate a network request (here you need to know that a network request is an asynchronous operation). The first network request (p1) takes 1s and the second one (P2) takes 2s.

let p1 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    resolve(Results of '1');
  }, 1000);
})
let p2 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    resolve(Results' 2 ');
  }, 2000);
})
// promise.all ([]) receives multiple asynchronous tasks and places them in an array
Promise.all([p1, p2]).then(results= > {// Results takes multiple arguments, so it's an array
  console.log(results);//[" result 1", "result 2"]
})
Copy the code

When you execute the code you will notice that it takes two seconds for the callback to complete, waiting for all network requests to succeed.

Promise. Race () method

Promise.all() waits for each asynchronous task to complete, whichever is slowest. Promise.race() is whoever finishes first, whichever is the fastest. So you can see I’m writing result instead of complex results in then. You can think of it as two network requests, you can think of it as requesting two servers at the same time, but the server with p1 request responds first, so we can get data from the server that responds quickly.

let p1 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    resolve(Results of '1');
  }, 1000);
})
let p2 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    resolve(Results' 2 ');
  }, 2000);
})
// promise.race ([]) receives multiple asynchronous tasks into an array
Promise.race([p1, p2]).then(result= > {// Result will accept only one parameter, which completes first
  console.log(result);
})
Copy the code
Summary: Promis encapsulates asynchronous operations. The idea is that instead of processing the code that needs to be executed in the callback function, you put the code that needs to be executed in the corresponding area of the then() or catch() method, and then call it through resolve() or reject(). When you separate code to make a chain call, you can think of a then or a catch as a point in a chain. We usually use promise to encapsulate asynchronous operations to form a good habit.
You can also follow me if you are interested:

CNSD: m0_46217225

Nuggets: buzz cut boy

Making: Buzz_cut

Wechat official account: web_mycode

Man with a buzz cut

Welcome to join QQ group to exchange programming knowledge:

Qq group: 808752665

My QQ: 2356924146

I will continue programming dry stuff.