I’m sure you all have a basic understanding of promises, especially in the React Vue project. Promises are used frequently. They were born to solve one thing — to make developers more reasonable and standardized in handling asynchronous operations

Because js is the design of the single thread, js has two queues and asynchronous tasks, synchronization task synchronization: as the name implies, is in order to carry out, asynchronous is no order, will according to the result of the execution time to return to task, found in the ajax request in the process of development, when we use the result of a request for the next request I parameters, the callback nested will form Into callback hell:

   $ajax({
       success(res1){
            $ajax({
               success(res2){
                    $ajax({
                       success(res3){
                           console.log('Callback hell is formed.')}})}})Copy the code

Promise was born to solve these problemsPromise A + specificationIn traditional writing, in order to get RES3, we have to rely on RES1 and RES2. Moreover, when there are more layers and more logical operations, the code is particularly difficult to maintain, which also increases the waiting time of the request. ES6 has standardized this, so there is the appearance of Promise. Promise objects allow us to handle asynchronous operations in a more logical and disciplined way.

The basic form of a Promise

    const prs = new Promise((resolve,reject) = >{
        resolve('Successful outcome')
        reject('Result of failure')})Copy the code

Three states of Promise

1. Pending: When a Promise is created, its state is pending, indicating its initial state.

2. Depressing: When the resolve method is called, the operation will be successful.

3. When the Rejected: reject method is invoked, the operation fails.

The state can only be changed from initialization to success or failure. The state is not reversible

.then and.catch methods

. Then indicates the service logic after successful processing

    prs.then(res= >{
        //res is the return value of success, which is the result of our resolve package
    })
Copy the code

. Catch indicates the service logic after processing failure

    prs.then(res= >{
        //res is the return value of success, which is the result of our resolve package
    }).catch(error= >{
        // Error is the result of a reject wrap
    })
Copy the code

This is a big pity. The promise.all () method accepts an array as parameter, the elements of which are Promise instance objects. When the state of the instance objects in the parameter is fulfilled, promise.all () will return.


    const prs1 = new Promise((resolve,reject) = >{
        resolve('PRS1 successfully executed')})const prs2 = new Promise((resolve,reject) = >{
        resolve('PRS2 executed successfully')})Promise.all([prs1,prs2]).then(res= >{Prs1 and PRS2 are executed successfullyPromise.all will return the correct array, and a single failure will resultPromiseAll ()}) failureCopy the code

This is a big pity. The promise.race () method accepts an array as parameters, the elements of which are the Promise instance objects. When the state of the instance objects in the parameters is fulfilled, the promise.race () will return the correct result.


    const prs1 = new Promise((resolve,reject) = >{
        resolve('PRS1 successfully executed')})const prs2 = new Promise((resolve,reject) = >{
        reject('PRS2 execution failed')})Promise.race([prs1,prs2]).then(res= >{prs1 succeeds, prS2 fails, butPromise.race() returns PRS1 as a result of successful execution, becausePromise.race() returns the result of the first successful execution})Copy the code

After reviewing the basics of promises, start writing them by hand

    class Promise {
      PromiseState = "pending"; // Ready
      PromiseResult = null; / / the result
      FULFILLED = "fulfilled"; // Successful status
      REJECTED = "rejected"; // Successful status
      fulfilledList = []; // Successfully callback the management array
      rejectedList = []; // Manage the array of failed callbacks
      constructor(executor) {
        this.initBind();
        try {
          executor(this.resolve, this.reject);
        } catch (error) {
          this.reject(error); }}initBind() {
        this.resolve = this.resolve.bind(this);
        this.reject = this.reject.bind(this);
      }
      // Successfully execute the function
      resolve = (value) = > {
        this.PromiseState = this.FULFILLED; // Change the state
        this.PromiseResult = value; / / assignment
      };
      reject = (reason) = > {
        this.PromiseState = this.REJECTED; // Change the state
        this.PromiseResult = reason; / / assignment
      };
      The then method can accept two callbacks as successful and failed callbacks
      then(onFulfilled, onRejected) {
        onFulfilled =
          typeof onFulfilled === "function" ? onFulfilled : (val) = > val;
        onRejected =
          typeof onRejected === "function"
            ? onRejected
            : (reason) = > {
                throw reason;
              };
        // Execute the callback function based on the state
        if (this.PromiseState === this.FULFILLED) onFulfilled(this.PromiseResult);
        if (this.PromiseState === this.REJECTED) onRejected(this.PromiseResult); }}// The basic then method is ready to test
    const prs = new Promise((resolve, reject) = > {
      resolve("Success");
      // reject(" reject ");
    });
    prs.then(
      (res) = > {
        console.log(res);
      },
      (error) = > {
        console.log(error); });// The console executes the corresponding result OK to continue refining the THEN method

Copy the code

At this time, our then method is synchronous and our result only judges the state as FULFILLED and REJECTED. If an asynchronous Promise is implemented in the new Promise, it cannot be implemented

    const prs = new Promise((resolve, reject) = > {
      setTimeout(() = > {
        resolve("Success");
      });
      // reject(" reject ");
    });
    prs.then((res) = > {
      console.log(res);
    });
    // The printed result is nullThen we need a management array of actuators to execute the methods stored in the array when the state changesCopy the code

The state of resolve and reject is Pedding due to the delayed entry of resolve and reject So instead of calling the resolve and reject methods in promises, we’ll continue to work on the code, which should have an array that manages the Promise’s execution queue when asynchronous, and then loop through the array

  fulfilledList = []; // Successfully callback the management array
  rejectedList = []; // Manage the array of failed callbacks
  // Add two management arrays to the class
  
  then(onFulfilled, onRejected) {
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (val) = > val;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) = > {
            throw reason;
          };
    // Determine the status
    if (this.PromiseState === this.FULFILLED) onFulfilled(this.PromiseResult);
    if (this.PromiseState === this.REJECTED) onRejected(this.PromiseResult);
    if (this.PromiseState == "pending") {
        / / when PromiseState status to pedding at this time According to our call. Then transfer to resolve and reject to, according to fulfilledList rejectedList two arrays management respectively
      this.fulfilledList.push((value) = > {
        setTimeout(() = > {
          onFulfilled(value);
        }, 0);
      });
      this.rejectedList.push((reason) = > {
        setTimeout(() = > {
          onFulfilled(reason);
        }, 0); }); }}The resolve and reject loop executes the methods saved in the two arrays
  resolve = (value) = > {
    this.PromiseState = this.FULFILLED; // Change the state
    this.PromiseResult = value; / / assignment
    this.fulfilledList.forEach((e) = > e(value));
  };
  reject = (reason) = > {
    this.PromiseState = this.REJECTED; // Change the state
    this.PromiseResult = reason; / / assignment
    this.fulfilledList.forEach((e) = > e(reason));
  };
  
  // Select * from ()
  const prs = new Promise((resolve, reject) = > {
      setTimeout(() = > {
        resolve("Success");
        // reject(" reject ");
      });
    });
    prs.then((res) = > {
      console.log(res);
    });
Copy the code

It’s working

Let’s start implementing the chain call of Promise

Take a look at the native Promise chain call

new Promise((resolve, reject) = > {
  resolve("Success");
})
.then(console.log(123))
.then((res) = > {
  console.log(res);
});

// Print 123 and success respectively
Copy the code

Support for chained calls means that the first then method must return a Promise, so we’ll continue with this feature

To be continued