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

The preface

Promises are so common in writing code that we don’t always want to see them without knowing why.

When I mentioned the Promise when the interviewer asked, the result did not understand, not good ~ ha ha ha

Introduction to the

The Promise object is used to represent the final completion (or failure) of an asynchronous operation and its resulting value.

A Promise must be in one of three states

  • Pending: The initial state, that is, not granted, nor rejected.
  • This is a big pity: it means that the operation will be successful
  • Rejected: Indicates that the operation fails

When pending is fulfilled or Rejected, the state will not change.

Solve a problem:

  1. Callback hell, code is hard to maintain
  2. Callbacks are subject to inversion of control

Realize the Promise

Grammar:

new Promise(executor)
Copy the code

The Promise implementation will execute the executor function immediately and pass in two functions. The Promise implementation will call resolve successfully and the state will become fulfilled. The Promise implementation will call reject and the state will become Rejected.

Design:

  1. Promise should be a constructor
  2. Passing in a parameter
function MyPromise(executor) { //1. Fix this, prevent resolve and reject from changing this, or use the arrow function let self = this; //2. The initial state of the Promise is pending self.state = "pending"; Self. value = undefined; // this is a big pity state array self. onrealdarr = []; // This is a big pity state array self. onrealdarr = []; Self. onRejectedArr = []; self.onRejectedArr = []; Function resolve(res) {//4.1 Determine whether the status is pending if (self.state! == "pending") return; // This is a big pity. State = "depressing "; //4.3 The result value is self.value = res; / / - 9. Call then array, backlog into self success. OnFulfilledArr. ForEach (item = > item ()); Function reject(err) {//5.1 Determine whether the state is pending if (self.state! == "pending") return; Self. State = "rejected"; //5.3 The result value is the passed parameter self.value = err; / / - 10. Call then array, backlog into self failure. OnRejectedArr. ForEach (item = > item ()); } //6. Execute executor try {executor(resolve, reject); }catch(err) { reject(err); }}Copy the code

Realize the Promise. Prototype. Then

The then method allows promises to support chained calls

Grammar:

p.then(onFulfilled[, onRejected]);
Copy the code

OnFulfilled and onRejected are optional

Note:

  1. The then method returns a Promise object
  2. Ondepressing is called when the state of the Promise changes to success, where the parameter is the one passed in to resolve
  3. Ondepressing is called when the promise state becomes a failure, with the parameter reject passing in the parameter
  4. The then method can be called multiple times
  5. Ondepressing is not a function, and then it will be replaced internally with (x) => x, which is the function that returns the final result of the promise as usual
  6. OnRejected is not a function and is internally replaced with a “Thrower” function.
        let test2 = new Promise((resolve, reject) => {
            resolve("hehe");
        });
        console.log(test2.then());
Copy the code

        let test2 = new Promise((resolve, reject) => {
            reject("hehe");
        });
        console.log(test2.then());
Copy the code

Design:

MyPromise.prototype.then = function (onFulfilled, onRejected) { //1. Fix this let self = this; //2. Judge whether ondepressing is a function if (typeof ondepressing! == "function") { onFulfilled = res => res; } //3. Check if (typeof onRejected! == "function") { onRejected = err => { throw err; }; // this will be a big pity if (self.state === "depressing ") {//4.1 Return the new promise object MyPromise((resolve, reject) => {try {// let x = ondepressing (self.value); If (x instanceof MyPromise) {if(x instanceof MyPromise) {if(x instanceof MyPromise) { err=>reject(err)); return; Resolve resolve(x); } catch (err) {//4.4 Catch error (err); }}); If (self. State === "rejected") {return new MyPromise((resolve, resolve)); Reject) => {try {let x = onRejected(self.value); if(x instanceof MyPromise) { x.then(res=>resolve(res), err=>reject(err)); return; } reject(x); } catch (err) { reject(err); }}); If (self.state === "pending") {return new MyPromise((resolve, resolve)); Reject) => {//6.1 since it is not clear whether to execute the successful state or the failed state, we need to store (7,8) in two arrays of Promise, and execute them when the state is finalized.  self.onFulfilledArr.push(() => { try { let x = onFulfilled(self.value); resolve(x); } catch (err) { reject(err); }}); self.onRejectedArr.push(() => { try { let x = onRejected(self.value); reject(x); } catch (err) { reject(err); }}); }); }}Copy the code

Realize the Promise. The prototype. The catch

The catch method is used for error handling in the promise combination.

This is the second argument function to the then method

Example:

        let temp = new Promise((resolve,reject)=>{
            reject("temp");
        });
        temp.then(val=>console.log(val)).then(()=>console.log("2")).catch(err=>console.log(err));
Copy the code

Output: temp

Design:

        MyPromise.prototype.catch = function(onRejected) {
            return this.then(undefined, onRejected);
        }
Copy the code

Realize the Promise. Resolve

Example: Pass in the Promise instance in the resolve method, returning itself

Design:

        let temp = new Promise((resolve,reject)=>{
            resolve("temp");
        });
        console.log(Promise.resolve(temp));
Copy the code

Pass in a non-PROMISE instance in the resolve method, return a new Promise value with a success state

        let temp = 1;
        console.log(Promise.resolve(temp));
Copy the code

Design:

    MyPromise.resolve = function(res) {
        if(res instanceof MyPromise) {
            return res;
        }
        return new MyPromise((resolve,reject)=>resolve(res));
    }
Copy the code

Realize the Promise. Reject

Return a Promise with a reason for the rejection

Design:

        MyPromise.reject = function(err) {
            return new MyPromise((resolve,reject)=>reject(err));
        }
Copy the code

Realize the Promise. All

Return a Promise in which a Promise in the iterator is rejected

When there are multiple Promise combinations, all of which are completed, the Promise returned by promise. all becomes completed asynchronously, and if one of them rejects, the returned Promise directly invokes the failed Promise’s callback function

Grammar:

Promise.all(iterable);
Copy the code

Iterable: An iterable

Design:

Mypromise.all = function(mpArr) {const res = []; myPromise.all = function(mpArr) {const res = []; return new MyPromise((resolve, reject) => { mpArr.forEach((item, index) => { MyPromise.resolve(item).then(val=>{ res.push(val); If (index + 1 == mpar.length) {resolve(res); }}, err => {reject(err); }); }); }); }Copy the code

Realize the Promise. Race

Returns a promise that is resolved or rejected once a promise in the iterator is resolved or rejected.

That’s the Promise in the iterator that executes whoever finishes first

Grammar:

Promise.race(iterable);
Copy the code

Design:

        MyPromise.race = function(mpArr) {
            return new MyPromise((resolve, reject) => {
                mpArr.forEach(item=>{
                    MyPromise.resolve(item).then(val=>{
                        resolve(val);
                    }, err => {
                        reject(err);
                    });
                });
            });
        }
Copy the code

conclusion

Promise was few and far between in the pen tests I encountered, but I asked a lot in interviews. The accumulation of knowledge is not too much

Reference: MDN | Promise