Promise 大法-手撕promise

一、Promise使用

1、没有Promise之前的处理

// 以前是使用回调函数
// 这种回调的方式有很多的弊端:
//  1> 如果是我们自己缝制的requestData,那么我们在封装的时候必须自己设计好callback名称
//  2> 如果是别人封装的,那我们必须去看别人的源码,看参数等,才能获取到结果

// request.js
function requestData(url, successCallback, errorCallback) {
  // 模拟网络请求
  setTimeout(() => {
    // 拿到请求的结果
    // url传入的是chen, 请求成功
    if (url === "chen") {
      // 成功
      let names = ["a", "b", "c", "d", "e", "f"];
      successCallback(names);
    } else {
      // 失败
      let errMessage = "请求失败";
      failCallback(errMessage);
    }
  }, 3000);
}

requestData(
  "chen",
  () => {
    console.log("成功他妈");
  },
  () => {
    console.log("失败他爹");
  }
);

2、promise的基本使用

class Person {
  constructor(callback) {
    let foo = function () {};
    let bar = function () {};
    callback(foo, bar);
  }
}
// const p = new Person("chen", 23);
const p = new Person((foo, bar) => {
  console.log("hello");
  // 这两个foo, bar又是函数,本身是可以执行的
});

// promise需要传入一个回调函数() => {}, 传入的这个函数会立即执行, 这个函数叫executor
const promise = new Promise((resolve, reject) => {
  console.log("promise传入的参数被执行了");
  // 本身是可以执行的
  resolve();    // resolve(), 来到promise.then(() =>{})
  // reject();  如果是调用reject(), 它会来到promise.catch(()=>{})
});

// then方法传入的函数,会在promise执行resolve函数是被回调。
promise.then(() => {});

3、异步请求的promise改造

// request.js
function requestData(url) {
  // 异步请求的代码会被放入到executor中
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url === "chen") {
        let names = ["a", "b", "c"];
        resolve(names);
      } else {
        // 失败
        let errMessage = "请求失败";
        reject(errMessage);
      }
    }, 3000);
  });
}

// requestData(
//   "chen",
//   () => {
//     console.log("成功他妈");
//   },
//   () => {
//     console.log("失败他爹");
//   }
// );

const promise = requestData("chen");
promise.then((res) => {
  console.log("成功 " + res);
});
promise.catch(() => {
  console.log("失败");
});
// 开发中一般直接写成这样
promise
  .then(() => {
    console.log("成功");
  })
  .catch(() => {
    console.log("失败");
  });
// 其实then里面也是可以放两个函数的, 第一是成功的回调,第二个是执行reject是的回调
promise.then(
  (res) => {
    console.log('成功');
  },
  (err) => {}
);

4、promise的resolve详解

// const promise = new Promise((resolve, reject) => {});
// promise.then(
//   (res) => {},
//   (err) => {}
// );

// 完全等价于下面的写法
// 给promise划分状态: pedding
// Promise状态一旦确定下来,那么就是不可更改的(锁定)
new Promise((resolve, reject) => {
  console.log("----------------直接执行"); // promise处于pedding状态
  resolve(res);
  reject(res); //这行代码是没有意义的,已经锁定了
})
  .then((res) => {
    // fulfiled状态(已固定)
    console.log("res成功");
  })
  .catch((err) => {
    // rejected状态(已拒绝)
    console.log("res失败");
  });

5、Promise的resolve参数

/**
 * resolve(参数)
 *    1> 普通的值或者对象 pedding -> fulfiled
 *    2> 传入一个Promise, 那么当前的Promise的状态会有传入的Promise来决定
 *       相当于状态进行移交
 *
 *    3> 传入一个对象,并且这个对象有实现then方法,那么也会执行该then方法,并且有该then方法决定后续状态
 */

// 2.传入一个Promise
// new Promise((resolve, reject) => {
//   // resolve({ name: "chen" }); //普通的对象
//   resolve(
//     new Promise((resolve, reject) => {
//       // 当传入的是Promise的时候,需要先调用这个promise
//       // resolve('aaaa'); //来到下面then中的res
//       reject("bbb"); //来到下面then中的err
//     })
//   );
// }).then(
//   (res) => {
//     console.log("res===", res);
//   },
//   (err) => {
//     console.log("err", err);
//   }
// );

// 3.传入一个对象
new Promise((resolve, reject) => {
  const obj = {
    then(resolve, reject) {
      resolve("resolve message");
    },
  };
  resolve(obj);
}).then(
  (res) => {
    console.log("res===", res);
  },
  (err) => {
    console.log("err", err);
  }
);

6、Promise中的then方法(重要)

// Promise有哪些对象方法
// console.log(Object.getOwnPropertyDescriptors(Promise.prototype));

const promise = new Promise(function (resolve, reject) {
  resolve("hahahha");
});

// 1.同一个Promise可以被多次调用then方法
// 当我们的resolveb被回调是,所有的then方法都会被回调
promise.then((res) => {
  console.log("res1===", res);
});
promise.then((res) => {
  console.log("res2===", res);
});

// 2.then方法传入的'回调函数'是可以有返回值的
//     then方法本身也是有返回值的,他的返回值是Promise
//     1> 如果我们返回的是一个普通的值(数值/字符串/普通对象/undefined),那么这个普通的值会被当成Promise中的resolve值
// 链式调用
promise
  .then((res) => {
    // 相当于new Promise((resolve, reject) =>{ resolve(111)})
    return 111; //这个值会被包裹成Promise。如果没有写返回值,返回的是undefined;
  })
  .then((res) => {
    console.log("res1---", res); //res1--- 111
    return "aaaa";
  })
  .then((res) => {
    console.log("res2===", res); //res2=== aaaa
  });
//  2> 如果返回的是一个Promise,依然会继续使用new Promise()进行包裹
promise
  .then((res) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(1111);
      }, 4000);
    });
  })
  .then((res) => {
    console.log(
      "这里也是会被延迟3秒的,由then里面return 传入的promise状态决定外面的promise状态",
      res
    );
  });

// 3> 如果返回的是一个对象,并且该对象实现了thenable,那么下一次.then(res)中的res,是由对象中的then决定的
promise
  .then((res) => {
    return {
      then: function (resolve, reject) {
        resolve(2222);
      },
    };
  })
  .then((res) => {
    console.log("对象中的then决定", res);
  });

7、Promise中的catch方法

const promise = new Promise((resolve, reject) => {
  reject("Error");
  // 其实抛出异常,也会执行第二个回调
  // throw new Error("reject error");
});

// 1、当executor抛出异常时,也是会调用错误捕获的回调函数的
promise.then(
  () => {},
  (err) => {
    console.log("err----", err);
  }
);
// 2、通过catch方法传入错误捕获的回调函数,只是另外一种写法
// promise/a+规范
promise.catch((err) => {
  console.log("err===", err);
});

// 3、es6中的语法糖
promise
  .then((res) => {
    return 4444;
  })
  .catch((err) => {
    console.log("es6红=====", err);
  });

  
// 4、catch方法的返回值.catch 返回值也是会被包裹成promise
const promise1 = new Promise((resolve, reject) => {
  reject("2222");
});

promise1
  .then((res) => {
    console.log("res====", res);
  })
  .catch((err) => {
    console.log("err:", err);
    return "catch return value";
  })
  .then((res) => {
    console.log("res result===", res);
  })
  .catch((err) => {
    console.log("err result===", err);
  });

8、Promise类方法 - resolve

// 类方法Promise.resolve:
// 将一个对象转成Promise

// 1.传入一个普通的值
const promise = Promise.resolve({
  name: "chen",
});

// 上面的写法,相当于下面
// const promise2 = new Promise((resolve, reject) => {
//   resolve({ name: "zhoaliu" });
// });
promise.then((res) => {
  console.log("res", res);
});

// 2.传入Promise
const promise3 = Promise.resolve(
  new Promise((resolve, reject) => {
    resolve(99999999);
  })
);
promise3.then((res) => {
  console.log("res===", res);
});

9、Promise类方法 - reject

const promise = Promise.reject("reject message");
// 相当于
// const promise2 = new Promise((resolve, reject) => {
//   reject("reject message");
// });

// reject不管传入什么值,都是一样的,
promise
  .then((res) => {
    console.log("res", res);
  })
  .catch((err) => {
    console.log("err===", err);
  });

11、Promise类方法 - all

// 创建多个promise
const p1 = new Promise((resolve, reject) => {
  resolve(111);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(222);
  }, 2020);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(222);
    // resolve("222");
  }, 3000);
});

// 需求:3个都有结果在调用后面的函数。当然,也可以放’aaa‘
// all也是返回一个Promise
// 意外:如果我们在拿到所有结果之前,有一个Promise变成了rejected, 那么整个Promise是rejected
Promise.all([p1, p2, p3, "aaa"])
  .then((res) => {
    console.log(res);
    // 返回的是一个数组,是按照数组中的顺序返回的
  })
  .catch((err) => {
    console.log(err);
  });

12、Promise类方法 - allSettled

const p1 = new Promise((resolve, reject) => {
  resolve(111);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(222);
  }, 2020);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(222); //allSettled是不会来到catch里面的
  }, 3000);
});

Promise.allSettled([p1, p2, p3, "aaa"])
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });

在这里插入图片描述
在这里插入图片描述
13、Promise类方法 - race

const p1 = new Promise((resolve, reject) => {
  resolve(111);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(222);
  }, 2020);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(222); //allSettled是不会来到catch里面的
  }, 3000);
});

// 只要有一个变成fulfilled, 那么就结束。
Promise.race([p1, p2, p3, "aaa"])
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });

14、Promise类方法 - any

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(111);
  }, 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(222);
  }, 2020);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(333); 
  }, 500);
});

Promise.any([p1, p2, p3])
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });

二、手写Promise

1、手写Promise-结构的设计

// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        this.status = PROMISE_STATE_FULFILED;
        this.value = value;
        console.log("resolve被调用了");
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        this.status = PROMISE_STATE_REJECTED;
      }
      console.log("reject被调用了");
    };
    executor(resolve, reject);
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("传入的函数直接被调用了 pending===");

  reject(111);
  resolve(222);
});

// 当我们调用then的时候,应该需要两个变量来保存
promise.then(
  (res) => {},
  (err) => {}
);

2、手写Promise-then方法的设计

// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        this.status = PROMISE_STATE_FULFILED;
        queueMicrotask(() => {
          this.value = value;
          console.log("resolve被调用了");
          // 我们需要执行then传进来的第一个函数
          this.onfulfilled(this.value);
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        this.status = PROMISE_STATE_REJECTED;
        queueMicrotask(() => {
          this.reason = reason;
          console.log("reject被调用了");
          // 我们需要执行then传进来的第二个函数
          this.onrejected(this.reason);
        });
      }
    };
    executor(resolve, reject);
  }

  then(onfulfilled, onrejected) {
    this.onfulfilled = onfulfilled;
    this.onrejected = onrejected;
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("传入的函数直接被调用了 pending===");

  reject(111);
  resolve(222);
});

// 当我们调用then的时候,应该需要两个变量来保存
promise.then(
  (res) => {
    console.log("res:", res);
  },
  (err) => {
    console.log("err", err);
  }
);

3.手写Promise-then方法优化1

// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;
    this.onfulfilledFns = [];
    this.onrejectedFns = [];

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          this.status = PROMISE_STATE_FULFILED;
          this.value = value;
          console.log("resolve被调用了");
          // 我们需要执行then传进来的第一个函数
          // this.onfulfilled(this.value);
          this.onfulfilledFns.forEach((fn) => fn(this.value));
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
     
        queueMicrotask(() => {
          this.status = PROMISE_STATE_REJECTED;
          this.reason = reason;
          console.log("reject被调用了");
          // 我们需要执行then传进来的第二个函数
          // this.onrejected(this.reason);
          this.onrejectedFns.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }

  then(onfulfilled, onrejected) {
    // 1.如果在then调用的时候,状态已经确定下来了
    if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
      onfulfilled(this.value);
    }
    if (this.status === PROMISE_STATE_REJECTED && onrejected) {
      onrejected(this.reason);
    }

    // 2.将成功回调和失败的回调放到数组中
    if (this.status === PROMISE_STATE_PENDING) {
      this.onfulfilledFns.push(onfulfilled);
      this.onrejectedFns.push(onrejected);
      // this.onfulfilled = onfulfilled;
      // this.onrejected = onrejected;
    }
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("传入的函数直接被调用了 pending===");

  reject(111);
  // resolve(222);
});

// 问题1: 调用then方法的多次调用
promise.then(
  (res) => {
    console.log("res===", res);
  },
  (err) => {
    console.log("err===", err);
  }
);

promise.then(
  (res) => {
    console.log("res2===", res);
  },
  (err) => {
    console.log("err2===", err);
  }
);

// 在确定Promise状态之后,在此调用我们的then
// 这是不会被回调的,因为前面放到函数遍历已经执行完了
setTimeout(() => {
  promise.then((res) => {
    console.log("res3---", res);
  });
}, 1000);

4. 手写Promise-then方法优化2

// 1.状态的设计
const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

// 工具函数封装
function execFnTryAndCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value);
    resolve(result);
  } catch (err) {
    reject(err);
  }
}
class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;
    this.onfulfilledFns = [];
    this.onrejectedFns = [];

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_FULFILED;
          this.value = value;
          // console.log("resolve被调用了");
          this.onfulfilledFns.forEach((fn) => fn(this.value));
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_REJECTED;
          this.reason = reason;
          // console.log("reject被调用了");
          this.onrejectedFns.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onfulfilled, onrejected) {
    return new MyPromise((resolve, reject) => {
      // 1.如果在then调用的时候,状态已经确定下来了
      if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
        // try {
        //   const value = onfulfilled(this.value);
        //   resolve(value);
        // } catch (err) {
        //   reject(err);
        // }
        // 简写
        execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATE_REJECTED && onrejected) {
        // try {
        //   const reason = onrejected(this.reason);
        //   resolve(reason);
        // } catch (err) {
        //   reject(err);
        // }
        execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
      }

      // 2.将成功回调和失败的回调放到数组中
      if (this.status === PROMISE_STATE_PENDING) {
        this.onfulfilledFns.push(() => {
          // try {
          //   const value = onfulfilled(this.value);
          //   resolve(value);
          // } catch (err) {
          //   reject(err);
          // }
          execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
        });
        this.onrejectedFns.push(() => {
          // try {
          //   const reason = onrejected(this.reason);
          //   resolve(reason);
          // } catch (err) {
          //   reject(err);
          // }
          execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
        });
        // this.onfulfilled = onfulfilled;
        // this.onrejected = onrejected;
      }
    });
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("状态 pending===");
  // reject(111);
  // throw new Error("executor error");
  resolve(222);
});

promise
  .then(
    (res) => {
      console.log("res1:", res);
      return 'aaa'
      // throw new Error("错误");
    },
    (err) => {
      console.log("err1:", err);
      return "bbb";
    }
  )
  .then(
    (res) => {
      console.log("res2:", res);
    },
    // 只有上一个中抛出异常,才会来到这个catch
    (err) => {
      console.log("err2", err);
    }
  );

5. 手写Promise-catch方法设计

const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

function execFnTryAndCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value);
    resolve(result);
  } catch (err) {
    reject(err);
  }
}
class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;
    this.onfulfilledFns = [];
    this.onrejectedFns = [];

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_FULFILED;
          this.value = value;
          // console.log("resolve被调用了");
          this.onfulfilledFns.forEach((fn) => fn(this.value));
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_REJECTED;
          this.reason = reason;
          // console.log("reject被调用了");
          this.onrejectedFns.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onfulfilled, onrejected) {
    onrejected =
      onrejected === undefined
        ? (err) => {
            throw err;
          }
        : onrejected;
    return new MyPromise((resolve, reject) => {
      // 1.如果在then调用的时候,状态已经确定下来了
      if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
        execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATE_REJECTED && onrejected) {
        execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
      }

      // 2.将成功回调和失败的回调放到数组中
      if (this.status === PROMISE_STATE_PENDING) {
        if (onfulfilled)
          this.onfulfilledFns.push(() => {
            execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
          });
        if (onrejected)
          this.onrejectedFns.push(() => {
            execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
          });
      }
    });
  }

  catch(onrejected) {
    this.then(undefined, onrejected);
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("状态 pending===");
  reject(111);
  // throw new Error("executor error");
  // resolve(222);
});

// 如果then第二个参数不传,就交给catch。如果传了,就给then第二个参数。
promise
  .then((res) => {
    console.log("res1:", res);
    // throw new Error("错误");
  })
  .catch((err) => {
    console.log("err1", err);
  });

6. 手写Promise-finnally方法设计

const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

function execFnTryAndCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value);
    resolve(result);
  } catch (err) {
    reject(err);
  }
}
class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;
    this.onfulfilledFns = [];
    this.onrejectedFns = [];

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_FULFILED;
          this.value = value;
          // console.log("resolve被调用了");
          this.onfulfilledFns.forEach((fn) => fn(this.value));
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_REJECTED;
          this.reason = reason;
          // console.log("reject被调用了");
          this.onrejectedFns.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onfulfilled, onrejected) {
    onrejected =
      onrejected === undefined
        ? (err) => {
            throw err;
          }
        : onrejected;

    const defaultOnFulfilled = (value) => {
      return value;
    };
    onfulfilled = onfulfilled || defaultOnFulfilled;
    
    return new MyPromise((resolve, reject) => {
      // 1.如果在then调用的时候,状态已经确定下来了
      if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
        execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATE_REJECTED && onrejected) {
        execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
      }

      // 2.将成功回调和失败的回调放到数组中
      if (this.status === PROMISE_STATE_PENDING) {
        if (onfulfilled)
          this.onfulfilledFns.push(() => {
            execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
          });
        if (onrejected)
          this.onrejectedFns.push(() => {
            execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
          });
      }
    });
  }

  catch(onrejected) {
    return this.then(undefined, onrejected);
  }

  // 不管成功还是失败,都调onfinally()
  finally(onfinally) {
    this.then(
      () => {
        onfinally();
      },
      () => {
        onfinally();
      }
    );
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("状态 pending===");
  // reject(111);
  // throw new Error("executor error");
  resolve(222);
});

// 如果then第二个参数不传,就交给catch。如果传了,就给then第二个参数。
promise
  .then((res) => {
    console.log("res1:", res);
    return "aaaa";
  })
  .catch((err) => {
    console.log("err1", err);
  })
  .finally(() => {
    console.log("最终");
  });

6. 手写Promise-resolve-reject 方法设计

const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

function execFnTryAndCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value);
    resolve(result);
  } catch (err) {
    reject(err);
  }
}
class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;
    this.onfulfilledFns = [];
    this.onrejectedFns = [];

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_FULFILED;
          this.value = value;
          // console.log("resolve被调用了");
          this.onfulfilledFns.forEach((fn) => fn(this.value));
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_REJECTED;
          this.reason = reason;
          // console.log("reject被调用了");
          this.onrejectedFns.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onfulfilled, onrejected) {
    onrejected =
      onrejected === undefined
        ? (err) => {
          throw err;
        }
        : onrejected;

    const defaultOnFulfilled = (value) => {
      return value;
    };
    onfulfilled = onfulfilled || defaultOnFulfilled;

    return new MyPromise((resolve, reject) => {
      // 1.如果在then调用的时候,状态已经确定下来了
      if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
        execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATE_REJECTED && onrejected) {
        execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
      }

      // 2.将成功回调和失败的回调放到数组中
      if (this.status === PROMISE_STATE_PENDING) {
        if (onfulfilled)
          this.onfulfilledFns.push(() => {
            execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
          });
        if (onrejected)
          this.onrejectedFns.push(() => {
            execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
          });
      }
    });
  }

  catch(onrejected) {
    return this.then(undefined, onrejected);
  }

  // 不管成功还是失败,都调onfinally()
  finally(onfinally) {
    this.then(
      () => {
        onfinally();
      },
      () => {
        onfinally();
      }
    );
  }

  static resolve(value) {
    return new MyPromise((resolve) => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }
}

MyPromise.resolve('hello world').then(res => {
  console.log('res', res)
})
MyPromise.reject('hello world').catch(err => {
  console.log('err', err)
})

7. 手写Promise-all-allSettled 方法设计

const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

function execFnTryAndCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value);
    resolve(result);
  } catch (err) {
    reject(err);
  }
}
class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;
    this.onfulfilledFns = [];
    this.onrejectedFns = [];

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_FULFILED;
          this.value = value;
          // console.log("resolve被调用了");
          this.onfulfilledFns.forEach((fn) => fn(this.value));
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_REJECTED;
          this.reason = reason;
          // console.log("reject被调用了");
          this.onrejectedFns.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onfulfilled, onrejected) {
    onrejected =
      onrejected === undefined
        ? (err) => {
          throw err;
        }
        : onrejected;

    const defaultOnFulfilled = (value) => {
      return value;
    };
    onfulfilled = onfulfilled || defaultOnFulfilled;

    return new MyPromise((resolve, reject) => {
      // 1.如果在then调用的时候,状态已经确定下来了
      if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
        execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATE_REJECTED && onrejected) {
        execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
      }

      // 2.将成功回调和失败的回调放到数组中
      if (this.status === PROMISE_STATE_PENDING) {
        if (onfulfilled)
          this.onfulfilledFns.push(() => {
            execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
          });
        if (onrejected)
          this.onrejectedFns.push(() => {
            execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
          });
      }
    });
  }

  catch(onrejected) {
    return this.then(undefined, onrejected);
  }

  // 不管成功还是失败,都调onfinally()
  finally(onfinally) {
    this.then(
      () => {
        onfinally();
      },
      () => {
        onfinally();
      }
    );
  }

  static resolve(value) {
    return new MyPromise((resolve) => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }

  static all(promises) {
    // 问题关键: 什么时候要执行resolve,什么时候要执行reject
    return new MyPromise((resolve, reject) => {
      const values = []
      promises.forEach(promise => {
        promise.then((res) => {
          values.push(res)
          if (values.length === promises.length) resolve(values)
        }, err => {
          reject(err)
        })
      })
    })
  }

  static allSettled(promises) {
    return new MyPromise((resolve) => {
      const results = []
      promises.forEach(promise => {
        promise.then(res => {
          results.push({
            status: PROMISE_STATE_FULFILED,
            value: res
          })
          if (results.length === promises.length) resolve(results)
        }, err => {
          results.push({
            status: PROMISE_STATE_REJECTED,
            value: err
          })
          if (results.length === promises.length) resolve(results)
        })
      })
    })
  }
}

const p1 = new MyPromise((resolve) => {
  setTimeout(() => { resolve(111) }, 1000);
})
const p2 = new MyPromise((resolve, reject) => {
  setTimeout(() => { reject(222) }, 2000);
})
const p3 = new MyPromise((resolve) => {
  setTimeout(() => { resolve(333) }, 3000);
})
// allSettled不会来到catch
MyPromise.allSettled([p1, p2, p3]).then((res) => {
  console.log(res)
})
// MyPromise.all([p1, p2, p3]).then((res) => {
//   console.log(res)
// }).catch(err => {
//   console.log(err)
// })

8. 手写Promise-race-any 方法设计

const PROMISE_STATE_PENDING = "pending";
const PROMISE_STATE_FULFILED = "fulfiled";
const PROMISE_STATE_REJECTED = "rejected";

function execFnTryAndCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value);
    resolve(result);
  } catch (err) {
    reject(err);
  }
}
class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATE_PENDING;
    this.value = null;
    this.reason = null;
    this.onfulfilledFns = [];
    this.onrejectedFns = [];

    const resolve = (value) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_FULFILED;
          this.value = value;
          // console.log("resolve被调用了");
          this.onfulfilledFns.forEach((fn) => fn(this.value));
        });
      }
    };
    const reject = (reason) => {
      if (this.status === PROMISE_STATE_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATE_PENDING) return;
          this.status = PROMISE_STATE_REJECTED;
          this.reason = reason;
          // console.log("reject被调用了");
          this.onrejectedFns.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onfulfilled, onrejected) {
    onrejected =
      onrejected === undefined
        ? (err) => {
          throw err;
        }
        : onrejected;

    const defaultOnFulfilled = (value) => {
      return value;
    };
    onfulfilled = onfulfilled || defaultOnFulfilled;

    return new MyPromise((resolve, reject) => {
      // 1.如果在then调用的时候,状态已经确定下来了
      if (this.status === PROMISE_STATE_FULFILED && onfulfilled) {
        execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATE_REJECTED && onrejected) {
        execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
      }

      // 2.将成功回调和失败的回调放到数组中
      if (this.status === PROMISE_STATE_PENDING) {
        if (onfulfilled)
          this.onfulfilledFns.push(() => {
            execFnTryAndCatchError(onfulfilled, this.value, resolve, reject);
          });
        if (onrejected)
          this.onrejectedFns.push(() => {
            execFnTryAndCatchError(onrejected, this.reason, resolve, reject);
          });
      }
    });
  }

  catch(onrejected) {
    return this.then(undefined, onrejected);
  }

  // 不管成功还是失败,都调onfinally()
  finally(onfinally) {
    this.then(
      () => {
        onfinally();
      },
      () => {
        onfinally();
      }
    );
  }

  static resolve(value) {
    return new MyPromise((resolve) => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }

  static all(promises) {
    // 问题关键: 什么时候要执行resolve,什么时候要执行reject
    return new MyPromise((resolve, reject) => {
      const values = []
      promises.forEach(promise => {
        promise.then((res) => {
          values.push(res)
          if (values.length === promises.length) resolve(values)
        }, err => {
          reject(err)
        })
      })
    })
  }

  static allSettled(promises) {
    return new MyPromise((resolve) => {
      const results = []
      promises.forEach(promise => {
        promise.then(res => {
          results.push({
            status: PROMISE_STATE_FULFILED,
            value: res
          })
          if (results.length === promises.length) resolve(results)
        }, err => {
          results.push({
            status: PROMISE_STATE_REJECTED,
            value: err
          })
          if (results.length === promises.length) resolve(results)
        })
      })
    })
  }

  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          resolve(err)
        })
      })
    })
  }

  static any(promises) {
    // resolve必须等到有一个成功的结果
    // reject所有的都失败才执行reject
    const reasons = [];
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(resolve, err => {
          reasons.push(err)
          if (reasons.length === promises.length) reject(new AggregateError(reasons))
        })
      })
    })
  }
}

const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => { reject(111) }, 1000);
})
const p2 = new MyPromise((resolve, reject) => {
  setTimeout(() => { reject(222) }, 2000);
})
const p3 = new MyPromise((resolve, reject) => {
  setTimeout(() => { reject(333) }, 3000);
})

MyPromise.any([p1, p2, p3]).then((res) => {
  console.log(res)
}).catch(err => {
  console.log(err)
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值