Promise 思维导图

手写 Promise - 图1

1. resolve与reject

  • Promise的初始状态是pending
  • resolvereject的this指向永远指向当前的MyPromise实例,防止随着函数执行环境的改变而改变

    代码

    1. class MyPromise {
    2. constructor(executor) {
    3. this.initValue(); //初始化值
    4. this.initBind(); //初始化this指向
    5. executor(this.resolve, this.reject); //执行传进的函数
    6. }
    7. initBind() {
    8. this.resolve = this.resolve.bind(this);
    9. this.reject = this.reject.bind(this);
    10. }
    11. initValue() {
    12. this.promiseState = "pending";
    13. this.promiseResult = null;
    14. }
    15. resolve(value) {
    16. this.promiseState = "fulfilled";
    17. this.promiseResult = value;
    18. }
    19. reject(reason) {
    20. this.promiseState = "rejected";
    21. this.promiseResult = reason;
    22. }
    23. }

    测试

    ```javascript const test1 = new MyPromise((resolve, reject) => { resolve(“ok”); }); test1;

const test2 = new MyPromise((resolve, reject) => { reject(“no”); }); test2;

  1. <a name="SDpJD"></a>
  2. # 2. 状态只可变一次
  3. ```javascript
  4. resolve(value) {
  5. if (this.PromiseState !== "pending") return;
  6. this.promiseState = "fulfilled";
  7. this.promiseResult = value;
  8. }
  9. reject(reason) {
  10. if (this.PromiseState !== "pending") return;
  11. this.promiseState = "rejected";
  12. this.promiseResult = reason;
  13. }

3. throw

有抛出错误就等于执行 reject,用 try catch 包裹一下

  1. constructor(executor) {
  2. this.initValue(); //初始化值
  3. this.initBind(); //初始化this指向
  4. try {
  5. executor(this.resolve, this.reject); //执行传进的函数
  6. } catch (e) {
  7. this.reject(e);
  8. }
  9. }

4. then

  • then接收两个回调,一个是成功回调,一个是失败回调
  • 当Promise状态为fulfilled执行成功回调,为rejected执行失败回调
  • 如resolve或reject在定时器里,则定时器结束后再执行then
  • then支持链式调用,下一次then执行受上一次then返回值的影响
  1. then(onFulfilled, onRejected) {
  2. // 参数校验,确保一定是函数
  3. onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;
  4. // console.log(onFulfilled);
  5. onRejected =
  6. typeof onRejected === "function"
  7. ? onRejected
  8. : reason => {
  9. throw reason;
  10. };
  11. if (this.promiseState === "fulfilled") {
  12. // 如果当前为成功状态,执行第一个回调
  13. onFulfilled(this.promiseResult);
  14. } else if (this.promiseState === "rejected") {
  15. // 如果当前为失败状态,执行第二哥回调
  16. onRejected(this.promiseResult);
  17. }
  18. }
  1. const test = new MyPromise((resolve, reject) => {
  2. resolve("ok");
  3. }).then(
  4. res => console.log(res),
  5. err => console.log(err)
  6. );
  7. //ok

5. 定时器

如何保证有定时器的情况下,到规定的时间再执行回调?
我们可以正常执行 then 但是等到规定时间之后在执行 then 的回调

  • 怎么知道要执行回调 —— 怎么知道什么时候定时器结束 —— pending 状态转变为其他状态的时候
  • 一个 promise 可能有多个 then —— 用数组存
  1. initValue() {
  2. this.promiseState = "pending";
  3. this.promiseResult = null;
  4. this.onFulfilledCallbacks = [];
  5. this.onRejectedCallbacks = [];
  6. }
  1. resolve(value) {
  2. if (this.promiseState !== "pending") return;
  3. this.promiseState = "fulfilled";
  4. this.promiseResult = value;
  5. while (this.onFulfilledCallbacks.length) {
  6. this.onFulfilledCallbacks.shift()(this.promiseResult);
  7. }
  8. }
  9. reject(reason) {
  10. if (this.promiseState !== "pending") return;
  11. this.promiseState = "rejected";
  12. this.promiseResult = reason;
  13. while (this.onRejectedCallbacks.length) {
  14. this.onRejectedCallbacks.shift()(this.promiseResult);
  15. }
  16. }
  1. then(onFulfilled, onRejected) {
  2. // 参数校验,确保一定是函数
  3. onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;
  4. // console.log(onFulfilled);
  5. onRejected =
  6. typeof onRejected === "function"
  7. ? onRejected
  8. : reason => {
  9. throw reason;
  10. };
  11. if (this.promiseState === "fulfilled") {
  12. // 如果当前为成功状态,执行第一个回调
  13. onFulfilled(this.promiseResult);
  14. } else if (this.promiseState === "rejected") {
  15. // 如果当前为失败状态,执行第二哥回调
  16. onRejected(this.promiseResult);
  17. } else if (this.promiseState === "pending") {
  18. //状态仍是 pending,先保存
  19. this.onFulfilledCallbacks.push(onFulfilled.bind(this));
  20. this.onRejectedCallbacks.push(onRejected.bind(this));
  21. }
  22. }

测试

  1. const test2 = new MyPromise((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve("成功"); // 1秒后输出 成功
  4. // resolve('成功') // 1秒后输出 失败
  5. }, 1000);
  6. }).then(
  7. res => console.log(res),
  8. err => console.log(err)
  9. );

6. 链式调用

下一次then执行受上一次then返回值的影响

  • then方法本身会返回一个新的Promise对象
  • 如果返回值是promise对象,返回值为成功,新promise就是成功
  • 如果返回值是promise对象,返回值为失败,新promise就是失败
  • 如果返回值非promise对象,新promise对象就是成功,值为此返回值
  1. then(onFulfilled, onRejected) {
  2. // 参数校验,确保一定是函数
  3. onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;
  4. // console.log(onFulfilled);
  5. onRejected =
  6. typeof onRejected === "function"
  7. ? onRejected
  8. : reason => {
  9. throw reason;
  10. };
  11. const thenPromise = new MyPromise((resolve, reject) => {
  12. const resolvePromise = cb => {
  13. try {
  14. const x = cb(this.promiseResult);
  15. if (x === thenPromise) {
  16. throw new Error("不能返回自身");
  17. }
  18. if (x instanceof MyPromise) {
  19. x.then(resolve, reject);
  20. } else {
  21. //不是 promise 对象
  22. resolve(x);
  23. }
  24. } catch (e) {
  25. reject(e);
  26. throw new Error(e);
  27. }
  28. };
  29. if (this.promiseState === "fulfilled") {
  30. // 如果当前为成功状态,执行第一个回调
  31. resolvePromise(onFulfilled);
  32. } else if (this.promiseState === "rejected") {
  33. // 如果当前为失败状态,执行第二个回调
  34. resolvePromise(onRejected);
  35. } else if (this.promiseState === "pending") {
  36. //状态仍是 pending,先保存
  37. this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled));
  38. this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected));
  39. }
  40. });
  41. return thenPromise;
  42. }
  43. }

7. 微任务

resolvePromise函数异步执行就可以了

8. all

  • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
  • 如果所有Promise都成功,则返回成功结果数组
  • 如果有一个Promise失败,则返回这个失败结果

    1. static all(promises) {
    2. const result = [];
    3. let count = 0;
    4. return new MyPromise((resolve, reject) => {
    5. const addData = (index, value) => {
    6. result[index] = value;
    7. count++;
    8. if (count === promises.length) resolve(result);
    9. };
    10. promises.forEach((promise, index) => {
    11. if (promise instanceof MyPromise) {
    12. promise.then(
    13. res => {
    14. addData(index, res);
    15. },
    16. err => reject(err)
    17. );
    18. } else {
    19. addData(index, promise);
    20. }
    21. });
    22. });
    23. }

    9. race

  • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功

  • 哪个Promise最快得到结果,就返回那个结果,无论成功失败

    1. static race(promises) {
    2. return new MyPromise((resolve, reject) => {
    3. promises.forEach(promise => {
    4. if (promise instanceof MyPromise) {
    5. promise.then(
    6. res => {
    7. resolve(res);
    8. },
    9. err => {
    10. reject(err);
    11. }
    12. );
    13. } else {
    14. resolve(promise);
    15. }
    16. });
    17. });
    18. }

    10. allSettled

  • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功

  • 把每一个Promise的结果,集合成数组,返回

    1. static allSettled(promises) {
    2. return new Promise((resolve, reject) => {
    3. const res = [];
    4. let count = 0;
    5. const addData = (status, value, i) => {
    6. res[i] = {
    7. status,
    8. value,
    9. };
    10. count++;
    11. if (count === promises.length) {
    12. resolve(res);
    13. }
    14. };
    15. promises.forEach((promise, i) => {
    16. if (promise instanceof MyPromise) {
    17. promise.then(
    18. res => {
    19. addData("fulfilled", res, i);
    20. },
    21. err => {
    22. addData("rejected", err, i);
    23. }
    24. );
    25. } else {
    26. addData("fulfilled", promise, i);
    27. }
    28. });
    29. });
    30. }

    11. any

    any 就是 all 的反过来

  • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功

  • 如果有一个Promise成功,则返回这个成功结果
  • 如果所有Promise都失败,则报错
    1. static any(promises) {
    2. return new Promise((resolve, reject) => {
    3. let count = 0;
    4. promises.forEach(promise => {
    5. promise.then(
    6. val => {
    7. resolve(val);
    8. },
    9. err => {
    10. count++;
    11. if (count === promises.length) {
    12. reject(new AggregateError("All promises were rejected"));
    13. }
    14. }
    15. );
    16. });
    17. });
    18. }