What is a Promise

Promise is a constructor, a solution to asynchronous JAVASCRIPT programming (callback hell). In case it’s not clear, I wrote the case o.O at the end of this chapter. Let’s take a look at some of the basics of Promise.

Characteristics of Promise

  1. The state of the object is not affected by the outside world

    This is a big pity (which is Pending) which has failed.Copy the code
  2. Solidification of the state (once the state has changed, it will not change again)

    Pending -> Fulfilled
    Pending -> Rejected
    Copy the code

Promise to create

  • The constructor takes an executor function as an argument. The two arguments to this function, resolve and Reject, are functions that change the state of the Promise object. Resolve is to change the state of the Promise object from ‘in progress’ to ‘success’ Pending -> depressing. It is called when the asynchronous operation succeeds and the successful result is passed as a parameter to the corresponding callback function. Reject changes the state of the Promise object from ‘ongoing’ to ‘failed’ Pending -> Rejected. It is called when the asynchronous operation fails and the failure information is passed to the corresponding callback function as a parameter.

  • When is the executor function executed?

    let promise = new Promise((resolve, reject) => { console.log(1); }) console.log(2); // 1 2 // called immediately when new creates a Promise instance.Copy the code
  • After the Promise instance is generated, the then() method can be called to bind the callback function for the success/failure of the asynchronous operation. The then() method takes two callbacks as arguments, the first optional callback for the success state of the Promise object, and the second optional callback for the failure state of the Promise object.

    let promise = new Promise((resolve, reject) => { setTimeout(() =>{ Math.random() * 100 > 60 ? Resolve (' pass ') : reject(' fail ') }, 300) }) promise.then((result) => { console.log(result); }, (reason) => { console.log(reason); })Copy the code
  • Then () {resolve (); then() {resolve (); Therefore, it waits for all synchronization tasks of the current script to complete. Therefore, 3 is printed first and 2 is printed last.

    let promise = new Promise((resolve,reject) => { console.log(1); resolve(2); }) promise.then((res) => { console.log(res); }) console.log(3); / / 1 2 3Copy the code

The difference with timer asynchrony

  • First of all, we will briefly mention the JS code execution process: synchronous into the main thread, asynchronous will enter the Event Table and register functions. When the specified Event completes, the Event Table moves this function to the Event Queue. If the tasks in the main thread are empty after execution, the Event Queue will read the corresponding function and enter the main thread for execution. This process is repeated over and over again, known as an Event Loop.

  • JS asynchronous code, divided into macro tasks and micro tasks, they have their own task queue. Microtasks: Promise, process.nexttick (); Macro tasks: setTimeout, setInterval, Ajax, DOM events. There is a priority issue here. When the main thread is idle, it checks the microtask queue first and then goes to the macro task queue. So the following code execution order is 2 -> 4 -> 3 -> 1

    setTimeout(() => {
      console.log(1);
    }, 30)
    let promise = new Promise((resolve, reject) => {
      console.log(2);
      resolve(3);
    })
    promise.then((res) => {
      console.log(res);
    })
    console.log(4);
    Copy the code

The then method is called chained

  • The then() method adds a return function to the success and failure states of the Promise instance, which returns a new Promise instance, so the then() method can be followed by a chain call to another THEN () method.

    let promise = new Promise((resolve, reject) => { resolve(1); }) promise.then((result) => { console.log(result); return 2; }, (reason) => { console.log(reason); }). Then ((result) => {console.log(' then2: ${result} '); })Copy the code
  • If the callback in the previous THEN () method returned a Promise instance, the callback in the next THEN () method will be invoked based on the state of the previous Promise instance.

    let p = new Promise((resolve, reject) => { resolve('success'); }) p.then((result) => { console.log(result); // -> 'success' return new Promise((resolve, reject) => { reject(`error-.-`); }) }) .then((result) => { console.log(result); {console.log(reason) => {console.log(reason); // -> 'error-.-' })Copy the code

Catch method

  • The callback used to specify when an error occurs is equivalent to the second callback of the then() method.

    let promise = new Promise((resolve, reject) => { resolve(data); }) then(null, (reason) => {console.log(reason); }) // === promise.then((res) => { console.log(res); }) .catch((err) => { console.log(err); })Copy the code

State of curing

  • Once the state of the Promise object changes, it stays the same.

    let promise = new Promise((resolve, reject) => { resolve('Fulfilled'); // This will be depressing console.log(data); }) promise.then(res => console.log(res)). Catch (err => console.log(err)); // This is a big pityCopy the code

State dependent

  • The current status of P2 depends on the status of P1, and therefore the status of P2 becomes invalid.

    let p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject('fail')
      }, 1000)
    })
    
    let p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(p1)
      }, 500)
    })
    
    p2.then(res => console.log(res))
      .catch(err => console.log(err)); // -> fail
    Copy the code

All and race

  • Both are methods on the Promise constructor, promise.all (), that wrap multiple Promise instances into a new Promise instance. The return values for success and failure are different, with an array of results returned when all are successful and the error message that triggered the failed state first on failure.

  • Note that the array of success results obtained by promise.all () is the same as the order in which they were passed in.

    let promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('peace');
      }, 1000)
    })
    
    let promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('and');
      }, 2000)})
    
    let promise3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('love');
      }, 300)
    })
    
    let p = Promise.all([promise1, promise2, promise3]);
    
    console.log(p);
    p.then(res => console.log(res)) // -> ["peace", "and", "love"]
     .catch(err => console.log(`reject: ${err}`));
    Copy the code
  • Promise.race(), which has the same use but different functionality as promise.all (), is the one that gets the fastest return, whether the result itself is a success state or a failure state.

    let promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('peace');
      }, 1000)
    })
    
    let promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('and');
      }, 2000)})
    
    let promise3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('love');
      }, 300)
    })
    
    let p = Promise.race([promise1, promise2, promise3]);
    
    console.log(p);
    p.then(res => console.log(res)) // -> love
     .catch(err => console.log(`reject: ${err}`));
    Copy the code

Fix the callback hell problem

Const fs = require('fs'); Fs.readfile ('./name.txt', 'utf-8', (err, data) => {if(data){fs.readfile (data, 'utf-8', (err, err,) => {if(data){fs.readfile (data, 'utf-8', (err, data) => { if(data){ fs.readFile(data, 'utf-8', (err, data) => { console.log(data); Return new Promise(resolve, reject) => {fs.readfile (path, reject) => {fs.readfile (path, reject); 'utf-8', (err, data) => { if(data){ resolve(data); } }) }) } readFile('./name.txt').then(data => return readFile(data)) .then(data => return readFile(data)) .then(data => Console. log(data)) // Promisify function promisify (fn) {return function (... args) { return new Promise((resolve, reject) => { fn(... args, (err, data) => { if(err){ reject(err); }else{ resolve(data); }})})}}Copy the code