Promise notes (final version)

Posted by mtorbin on Sun, 20 Feb 2022 00:16:22 +0100

If you are Xiaobai, this set of information can help you become a big bull. If you have rich development experience, this set of information can help you break through the bottleneck
2022web full set of video tutorial front-end architecture H5 vue node applet Video + data + code + interview questions.

catalogue

1, Meet Promise

(1) Relevant knowledge and characteristics

(2) Promise first experience

(3) Promise practice

2, Promise Basics

(1) Basic knowledge

(2) Promise API and code

(3) Several key problems and codes

3, Custom encapsulated Promise (handwritten Promise, class version)

4, async and await

(1) Basic knowledge

(2) Code practice

#END (see station b for details ovo)

1, Meet Promise

(1) Relevant knowledge and characteristics

1. Promise is a new solution for asynchronous coding of js introduced by Es6

2. Syntax: Promise is a constructor

Functionally: Promise object is used to encapsulate an asynchronous operation and obtain its success / failure result value

3. Advantages:

① The way of specifying callback functions is more flexible (you can even specify multiple callback functions after the end of asynchronous tasks)

② Support chain call, which can solve the problem of callback hell

a. Callback Hell: callback functions are nested calls. The result of asynchronous execution of external callback functions is the condition for the execution of nested callbacks

b. Callback features: not easy to read, not easy to handle exceptions

c. Solution: Promise chained call

(2) Promise first experience

1. Use promise to realize a lucky draw. The specific requirements are as follows:

① Generate random number with 30% winning probability

② Click the button for 1s to display whether to win the prize

③ If you win the prize, congratulations will pop up, and you will get Wu Shixun's autograph and the surrounding gift bag

④ If you don't win the prize, you will pop up and make persistent efforts ovo

2. Code: (there are ordinary version and promise version in the code)

<body>
    <div class="container">
      <h1 class="header">Promise First experience</h1>
      <button>Click lucky draw</button>
    </div>
  </body>
  <script>
    //Generate random number with 30% winning probability
    //Click the button for 1s to display whether to win the prize
    //If you win the prize, congratulations will pop up, and you will get Wu Shixun's autograph and the surrounding gift bag
    //If you don't win the prize, you will pop up and make persistent efforts ovo

    //Generate random number
    function rand(m, n) {
      return Math.ceil(Math.random() * (n - m + 1)) + m - 1;
    }
    const btn = document.querySelector("button");
    btn.addEventListener("click", () => {
      /*
        //timer
      setTimeout(() => {
        //Get random numbers from 1-100
        let num = rand(1, 100);
        if (num <= 30) {
          alert("Congratulations on winning the prize. Wu Shixun's autograph and the surrounding gift bag ");
        } else {
          alert("Keep up the good work ovo ");
        }
      }, 1000);
      */

      //Promise wraps an asynchronous operation
      //Promise form
      //The parameter is a value of function type, with two formal parameters resolve and reject respectively
      //resolve resolves reject and rejects data that are all function types
      //When the asynchronous task succeeds, call resolve; reject is called when the asynchronous task fails
      const p = new Promise((resolve, reject) => {
        setTimeout(() => {
          //Get random numbers from 1-100
          let num = rand(1, 100);
          if (num <= 30) {
            resolve(num);
            //When resolve is called, the state of the promise object (i.e. p) is set to success
          } else {
            reject(num);
            //When resolve is called, the state of the promise object (that is, p) is set to failed
          }
        }, 1000);
      });

      //Implement resolve and reject
      //Call the then method and accept two parameters, both of which are function type data
      //The first parameter is the callback of success, and the second parameter is the callback of failure
      p.then(
        (value) => {
          alert(
            "Your number is:" +
              value +
              ",Congratulations on winning the prize. I won Wu Shixun's autograph and the surrounding gift bag"
          );
        },
        (reason) => {
          alert("Your number is:" + reason + ",Fail to win the prize and make persistent efforts ovo");
        }
      );
    });
  </script>

3. Results:

(3) Promise practice

1. Practice 1: fs reading files

1) ① fs function: read and write the computer hard disk

②fs.readFile(): read the file. The first parameter is the file path and the second parameter is a function

2) Code: (fs version and promise version are included in the code)

//fs function: read and write the computer hard disk
//Read a file content txt

//Introduce fs callback function form
const fs = require("fs");
//err is the parameter when an error occurs, and data is the read result
/*
fs.readFile("content.txt", (err, data) => {
  //If there is an error, an error is thrown
  if (err) throw err;
  //Otherwise, output the contents of the file
  console.log(data.toString());
});
*/

//Promise form
let p = new Promise((resolve, reject) => {
  fs.readFile("content.txt", (err, data) => {
    //readFile reading a file is an asynchronous operation
    //If it fails (reject is called if there is an error)
    if (err) reject(err);
    //If successful (call resolve if successful)
    resolve(data);
  });
});
//Call then
p.then(
  (value) => {
    console.log(value.toString());
  },
  (reason) => {
    console.log(reason);
  }
);

3) Result: enter node + file name in the terminal

2. Practice 2: promise encapsulates fs file reading operation

1) Explanation of relevant parameters:

① Encapsulate a function mineReadFile to read the contents of the file

② Parameter: path file path

③ Return: promise object

2) Code:

/**
 * Encapsulate a function mineReadFile to read the contents of the file
 * Parameter: path file path
 * Return: promise object
 */
function mineReadFile(path) {
  return new Promise((resolve, reject) => {
    //read file
    require("fs").readFile(path, (err, data) => {
      //reject is called if an error occurs
      if (err) reject(err);
      //resolve is called if successful
      resolve(data);
    });
  });
}

mineReadFile("content.txt").then(
  (value) => {
    //Output file content
    console.log(value.toString());
  },
  (reason) => {
    //Output error problem
    console.log(reason);
  }
);

3) Results:

3. Practice 3: promise sends AJAX requests

1) Code:

  <body>
    <div class="container">
      <h1>Promise encapsulation AJAX operation</h1>
      <button>Click send AJAX</button>
    </div>
  </body>
  <script>
    //Interface address https://api.apiopen.top/getJoke
    //Promise form
    const btn = document.querySelector("button");
    //Binding event
    btn.addEventListener("click", () => {
      const p = new Promise((resolve, reject) => {
        //1. Create object
        const xhr = new XMLHttpRequest();
        //2. Initialization
        xhr.open("GET", "https://api.apiopen.top/getJoke");
        //3. Send
        xhr.send();
        //4. Bind event processing response results
        xhr.onreadystatechange = () => {
          //Judgment response
          if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
              //Console output response body
              resolve(xhr.response);
            } else {
              //Console output response status code
              reject(xhr.status);
            }
          }
        };
      });
      //Call the then method
      p.then(
        (value) => {
          console.log(value);
        },
        (reason) => {
          console.warn(reason);
        }
      );
    });
  </script>

2) Results:

4. Practice 4: promise encapsulates AJAX requests

1) Basic requirements and parameters

① Encapsulate a function sendAJAX to send a GET AJAX request

② Parameter URL

③ Return result Promise object

2) Code:

/*
        Encapsulate a function sendAJAX to send a GET AJAX request
        Parameter URL
        Return result Promise object
        */
    function sendAJAX(url) {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.responseType = "json";
        xhr.open("GET", url);
        //send out
        xhr.send();
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4) {
            //Judge success
            if (xhr.status >= 200 && xhr.status < 300) {
              //Successful responder
              resolve(xhr.response);
            } else {
              //Failure status code
              reject(xhr.status);
            }
          }
        };
      });
    }

    sendAJAX("https://api.apiopen.top/getJoke").then(
      (value) => {
        console.log(value);
      },
      (reason) => {
        console.warn(reason);
      }
    );

3) Results:

5. Practice 5: util Promise style transformation with promise method

1) This method converts a callback based function into a Promise based function. This allows you to use Promise chains and async/await with callback based API s

2) Code:

//Introducing util module
const util = require("util");
//Introducing fs module
const fs = require("fs");
//Returns a new function
let mineReadFile = util.promisify(fs.readFile);

mineReadFile("content.txt").then(
  (value) => {
    console.log(value.toString());
  },
  (reason) => {
    console.log(reason);
  }
);

3) Results:

2, Promise Basics

(1) Basic knowledge

1. promise state: it is a property PromiseState (built-in) in the instance object

2. Promise status: pending, resolved / fully filled, rejected

① There are only two kinds of state changes: from pending - > resolved or from pending - > rejected

② A promise object can only change state once

③ The successful result data is generally called value, and the failed result data is generally called reason (a habit)

3. Value of promise object: a property PromiseResult in the instance object

① The results of success / failure in asynchronous tasks are saved

② resolve and reject functions can change or assign values to PromiseResult

4. Basic process of promise

New promise() - > execute asynchronous operation - > successfully execute resolve() / fail to execute reject() - > promise object - > callback corresponding method - > new promise object

(2) Promise API and code

1. promise constructor: Promise(excutor) {}

1) Executor function: executor (resolve, reject) = > {} ((resolve, reject) is called the executor function, and the part surrounded by orange is called the executor function)

2) resolve function: the function called when the internal definition is successful. Value = > {}

3) reject function: the function called when the internal definition fails, reason = > {}

**Note: * * the executor will immediately call synchronously within Promise, and the asynchronous operation will be executed in the executor

2. Promise.prototype.then method: (onResolved, onrejected) = > {}

1) onResolved function: successful callback function value = > {}

onReject function: failed callback function reason = > {}

2) Specify the success callback used to get the success value and the failure callback used to get the failure reason, and return a new promise object;

3. Promise.prototype.catch method (only failed callbacks can be executed): (onrejected) = > {}

1) onRejected function: failed callback function reason = > {}

4. Promise related methods

1)Promise.reject method: (reason) = > {}

Reason: the reason for the failure. A promise object is returned

2)Promise.all method: (promises) = > {}

Promises: an array containing n promises. A new promise is returned. Only if all promises are successful will it succeed. If one fails, it will be a failure

3)Promise.race method: (promises) = > {}

Promises: an array containing n promises. The state result of the first completed promise is the final result state

//resolve method
    //If the passed in parameter is an object of non promise type, the returned results are all successful promise objects
    //If the passed in parameter is promise object, the result of the parameter determines the result of resolve
    let p1 = Promise.resolve("sehun");
    console.log(p1);
    let p2 = Promise.resolve(
      new Promise((resolve, reject) => {
        resolve("OK");
        //reject('Error');
      })
    );
    console.log(p2);
    p2.catch((reason) => {
      console.log(p2);
    });

    //The reject method always returns a failed result
    //If the passed in parameter is an object of non promise type, the returned results are all failed promise objects
    //If the parameter passed in is a promise object, the result returned is still a failure
    let a = Promise.reject("sehun");
    console.log(a);
    let a2 = Promise.reject(
      new Promise((resolve, reject) => {
        resolve("OK");
        //reject('Error');
      })
    );
    console.log(a2);

    //all method
    let b = new Promise((resolve, reject) => {
      resolve("Ok");
    });
    let b1 = Promise.resolve("Success");
    let b2 = Promise.resolve("oh Yeah");
    //All promise s in the array succeed only when they succeed, and the returned result is an array composed of all successful results
    const result = Promise.all([b, b1, b2]);
    console.log(result);

    //race method
    let c = new Promise((resolve, reject) => {
      //resolve("Ok");
      setTimeout(() => {
        resolve("OK");
      }, 1000);
    });
    let c1 = Promise.resolve("Success");
    let c2 = Promise.resolve("oh Yeah");
    //All promise s in the array succeed only when they succeed, and the returned result is an array composed of all successful results
    const result1 = Promise.race([c, c1, c2]);
    console.log(result1);

(3) Several key problems and codes

1. How to change promise status?

1) resolve(value): if it is currently pending, it will become resolved;

2) reject(reason): if it is currently pending, it will become rejected;

3) Throw an exception: if it is currently pending, it will become rejected;

2. If a promise specifies multiple success / failure callback functions, will they be called?

A: it will be called when promise changes to the corresponding state

3. Change promise status and specify callback function who comes first and who comes later? (i.e. whether the status change is executed first or the then method callback is executed first)

1) It is possible to specify the callback first and then change the state under normal circumstances, but you can also change the state first and then specify the callback;

2) How to change the state first and then specify the callback?

a. Directly call resolve()/reject() in the actuator;

b. Delay a longer time before calling then();

3) When can I get the data? (that is, when the callback function is executed)

a. If the callback is specified first, when the state changes, the callback function will be called to get the data;

b. If the state is changed first, when the callback is specified, the callback function will be called to get the data.

4. promise. What determines the result status of the new promise returned by then()?

1) Determined by the execution result of the callback function specified by then

2)

① If an exception is thrown, the status of the new promise result changes to rejected, and reason is the exception thrown;

② If any value other than promise is returned, the status of the new promise result changes to resolved, and value is the returned value;

③ If a promise is returned, the result status of the new promise is determined by the returned promise;

5. How promise connects multiple operation tasks in series

1) Promise's then function returns a new promise object, which can be changed into a chain call of then;

2) Concatenate multiple synchronous / asynchronous tasks through the chain call of then

6. promise abnormal penetration

1) When using promise's then chain call, you can specify the failed callback at the end;

2) If any of the previous operations is abnormal, it will be transferred to the last failed callback for processing;

7. Interrupt promise chain

1) Meaning: when using promise's then chain call, interrupt in the middle and no longer call the subsequent callback function;

2) Methods: return a promise object in pending status in the callback function;

// 1. Change promise status
    let p = new Promise((resolve, reject) => {
      //1. resolve function
      //resolve("ok"); // pending => resolved/fulfilled
      //2. reject function
      //reject("error"); // pending => rejected
      //3. Throw an error
      throw "error!";
    });
    console.log(p);

    //2. Call multiple callbacks
    // The callback is executed only when the state changes
    let p = new Promise((resolve, reject) => {
      resolve("sehunBBQ");
    });
    // Specify callback - 1
    p.then((value) => {
      console.log(value);
    });
    // Callback - specify 2
    p.then((value) => {
      alert(value);
    });
    

    // 3.
    //① Change the state first and then execute the callback: when the task in the function of the executor is a synchronization task
    let p = new Promise((resolve, reject) => {
      resolve("sehunBBQ");
    });
    // Specify callback
    p.then((value) => {
      console.log(value);
    });
    //② The situation of executing callback first and then changing the state: when the task in the function of the executor is asynchronous
    let p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("BBQのSehun");
      }, 1000);
    });
    p1.then(
      (value) => {
        console.log(value + "!");
      },
      (reason) => {}
    );

    // 4. promise. What determines the result status of the new promise returned by then()
    let p = new Promise((resolve, reject) => {
      resolve("sehunBBQ");
    });
    //Execute then method
    let result = p.then(
      (value) => {
        // console.log(value);
        // 1. Throw an error
        //throw "sehun: error!";
        // 2. The returned result is not a promise object
        //return "sehun?";
        // 3. The returned result is a promise object
        return new Promise((resolve, reject) => {
          //resolve("success!sehun!");
          reject("error!sehun!");
        });
      },
      (reason) => {
        console.warn(reason);
      }
    );
    console.log(result);

    // 5. How promise connects multiple operation tasks in series
    let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("BBQのsehun");
      }, 1000);
    });

    p.then((value) => {
      return new Promise((resolve, reject) => {
        resolve("sehun!BBQ!");
      });
    })
      .then((value) => {
        console.log("?" + value);
      })
      .then((value) => {
        console.log(value); // The print will be undefined 
  //Because the result returned by the previous then is not a promise object, the status is successful and the return value is undefined
      });

    // 6. promise abnormal penetration
    let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("BBQのsehun");
        //reject("error");
      }, 1000);
    });

    p.then((value) => {
      return new Promise((resolve, reject) => {
        resolve("sehun!BBQ!");
      });
    })
      .then((value) => {
        //console.log("?");
        throw "error!";
      })
      .then((value) => {
        console.log("?sehun");
      })
      .catch((reason) => {
        console.warn(reason);
      });

    // 7. Interrupt promise chain
    let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("ok");
        //reject("error");
      }, 1000);
    });

    //Break chain: returns a pending promise object
    //Because the callback function is called only when the state changes, you need a promise in pending state if you want the subsequent callback function not to be executed
    p.then((value) => {
      console.log("sehunの");
      return new Promise(() => {});
    })
      .then((value) => {
        console.log("?");
      })
      .then((value) => {
        console.log("?->sehun");
      })
      .catch((reason) => {
        console.warn(reason);
      });

3, Custom encapsulated Promise (handwritten Promise, class version)

1. The specific code is as follows:

class Promise {
  //Construction method
  constructor(executor) {
    //Add attribute
    this.PromiseState = "pending";
    this.PromiseResult = null;
    //Declare a property
    this.callbacks = [];

    //Save the value of this of the instance object
    const self = this; // self _ This that (three commonly used names)

    //Declare resolve and reject
    //resolve function
    function resolve(data) {
      // Judge the status, because the object status can only be modified once
      if (self.PromiseState !== "pending") return;
      //1. Modify the state of the object (promiseState)
      self.PromiseState = "fulfilled"; // resolved
      //2. Set the object result value (promiseResult)
      self.PromiseResult = data;
      //Call successful callback
      setTimeout(() => {
        self.callbacks.forEach((item) => {
          item.onResolved(data);
        });
      });
    }
    //reject function
    function reject(reason) {
      // Judge the status, because the object status can only be modified once
      if (self.PromiseState !== "pending") return;
      //1. Modify the state of the object (promiseState)
      self.PromiseState = "rejected";
      //2. Set the object result value (promiseResult)
      self.PromiseResult = reason;
      //Execution failure callback
      setTimeout(() => {
        self.callbacks.forEach((item) => {
          item.onRejected(reason);
        });
      });
    }

    try {
      //Synchronous call to executor function
      executor(resolve, reject);
    } catch (e) {
      //Failed to modify Promise object status to
      reject(e);
    }
  }

  // then method encapsulation
  then(onResolved, onRejected) {
    const self = this;
    //Determine callback function parameters
    if (typeof onRejected !== "function") {
      //Create an initial value
      onRejected = (reason) => {
        throw reason;
      };
    }
    //pass by value
    if (typeof onResolved !== "function") {
      //Create a default value
      onResolved = (value) => {
        value;
      };
    }

    return new Promise((resolve, reject) => {
      //Encapsulation function
      function callback(type) {
        try {
          //Get the execution result of the callback function
          let res = type(self.PromiseResult); //The specific implementation method is determined by then written by yourself
          if (res instanceof Promise) {
            //If it is a promise type object
            res.then(
              (v) => {
                resolve(v);
              },
              (r) => {
                reject(r);
              }
            );
          } else {
            //The object status of the result is success
            resolve(res);
          }
        } catch (e) {
          reject(e);
        }
      }
      //Judgment state
      if (this.PromiseState !== "rejected") {
        setTimeout(() => {
          callback(onResolved);
        });
      }
      if (this.PromiseState === "rejected") {
        setTimeout(() => {
          callback(onRejected);
        });
      }
      if (this.PromiseState === "pending") {
        //Save callback function!!!!!
        this.callbacks.push({
          onResolved: function () {
            callback(onResolved);
          },
          onRejected: function () {
            callback(onRejected);
          },
        });
      }
    });
  }

  //catch method encapsulation
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

  //The resolve method encapsulation is described with static, indicating that it belongs to the static object of the class
  static resolve(value) {
    //Returns a promise object
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        value.then(
          (v) => {
            resolve(v);
          },
          (r) => {
            reject(r);
          }
        );
      } else {
        resolve(value);
      }
    });
  }

  //reject method encapsulation
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    });
  }

  //all method encapsulation
  static all(promises) {
    return new Promise((resolve, reject) => {
      //Declare variable
      let count = 0;
      let arr = []; //Store successful results
      //ergodic
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (v) => {
            //The object status is known successfully
            //Only when each promise object is successful can the resolve function be executed to make the all method successful
            count++;
            //Store the successful result of the current promise object into the array
            arr[i] = v;
            //Judge count
            if (count === promises.length) {
              resolve(arr);
            }
          },
          (r) => {
            reject(r);
          }
        );
      }
    });
  }

  //race method encapsulation
  static race(promises) {
    return new Promise((resolve, reject) => {
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (v) => {
            //Modify the status of the returned object to success
            resolve(v);
          },
          (r) => {
            //Failed to modify the status of the returned result
            reject(r);
          }
        );
      }
    });
  }
}

4, async and await

(1) Basic knowledge

1. Async function

1) The return value of the function is promise object;

2) The result of promise object is determined by the return value executed by async function;

2. await expression

1) The expression on the right side of await is generally promise object, but it can also be other values;

2) If the expression is a promise object, await returns the value of promise success;

3) If the expression is another value, this value is directly used as the return value of await;

1. 2 Notes:

1) Await must be written in async function, but there can be no await in async function;

2) If the promise of await fails, an exception will be thrown, which needs to be caught through try... catch

(2) Code practice

1. Practice 1: async function

1) Code:

<script>
      // Same rule as then's return result
      async function main() {
        //1. If the return value is a non promise type data
        // return 'sehun';
        //2. If the return value is a promise object
        /*
        return new Promise((resolve, reject) => {
          reject("oh");
        });
        */
        //3. Throw an exception
        //throw "error!";
      }

      let result = main();

      console.log(result);
    </script>

2) Results:

2. Practice 2: await expression

1) Code:

async function main() {
        //1. The right side is promise
        let p = new Promise((resolve, reject) => {
          reject("error");
        });
        //let res = await p;
        //2. Other types of data are on the right
        //res = await "sehunBBQ";
        //3. The right side is the promise object. Promise failed
        try {
          let res = await p;
        } catch (e) {
          console.warn(e);
        }
      }

      main();

2) Results:

3. Practice 3: the combination of async and await expressions

1) Code:

/**
 * Read the contents of three files 1, 2 and 3 in the resource folder
 * Splice for output
 */

const fs = require("fs");
const util = require("util");
const mineReadFile = util.promisify(fs.readFile);

//Using callback function
/**
 * fs.readFile("resource/1.txt", (err, data1) => {
  if (err) throw err;
  fs.readFile("resource/2.txt", (err, data2) => {
    if (err) throw err;
    fs.readFile("resource/3.txt", (err, data3) => {
      if (err) throw err;
      console.log(data1 + +"
" + data2 + "
" + data3);
    });
  });
});
 */

//async and await
async function main() {
  try {
    //Read the contents of the first file
    let d1 = await mineReadFile("resource/1.txt");
    let d2 = await mineReadFile("resource/2.txt");
    let d3 = await mineReadFile("resource/3.txt");

    console.log(d1 + d2 + "
" + d3);
  } catch (e) {
    console.warn(e);
  }
}

main();

2) Results:

4. Practice 4: send AJAX requests with async and await expressions

1) Code:

<body>
    <button>Click to get the piece</button>
  </body>
  <script>
    //Segment sub interface: https://api.apiopen.top/getJoke
    function sendAJAX(url) {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.responseType = "json";
        xhr.open("GET", url);
        //send out
        xhr.send();
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4) {
            //Judge success
            if (xhr.status >= 200 && xhr.status < 300) {
              //Successful responder
              resolve(xhr.response);
            } else {
              //Failure status code
              reject(xhr.status);
            }
          }
        };
      });
    }

    //Click the button to send an ajax request to get the segment
    let btn = document.querySelector("button");
    btn.addEventListener("click", async () => {
      //Get segment information
      let duanzi = await sendAJAX("https://api.apiopen.top/getJoke");
      console.log(duanzi);
    });
  </script>

2) Results:

#END (see station b for details ovo)

Topics: Javascript Front-end html Interview