如何快速记住手写Promise方法的那些代码

103 阅读4分钟

作为大龄失业青年,在这个就业率低的时代,我也很无奈。

但是!!!!

八股文,该背还得背

那么

对于面试中的遇到的,手写Promise的方法,比如 Promise.race、Promise.all、Promise.any、Promise.allSettled

怎么能快速进行呢

特别提示⚠️:小菜鸟自嗨中,大佬可以麻烦退出,不浪费时间

为什么要先说 Promise.race,因为 Promise.race 是可以为后续的 Promise.all、Promise.any、Promise.allSettled 搭建基础框架的。后续的三个代码都是在 Promise.race 上缝缝补补的。

Promise.race

首先,Promise.race()方法是将多个 Promise 实例,包装成一个新的 Promise 实例。因此,我们需要返回 Promise

Promise.race = function (arr) {
  return new Promise((resolve, reject) => {})
}

再者,传入的数组中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

遍历数组,用 for 循环,对 arr[i] 进行操作,把结果返回。

for (let i = 0; i < arr.length; i++) {
  arr[i].then(resolve, reject)
}

最后,对非 Promise 进行处理

if (!(arr[i] instanceof Promise)) {
  Promise.resolve(arr[i]).then(resolve, reject)
}

组合代码

Promise.race = function (arr) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arr.length; i++) {
      if (!(arr[i] instanceof Promise)) {
        Promise.resolve(arr[i]).then(resolve, reject)
      } else {
        arr[i].then(resolve, reject)
      }
    }
  })
}

Promise.all

接下来,需要用到 Promise.race 的代码,框架抄下来,改个名字

Promise.all = function (arr) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arr.length; i++) {
      if (!(arr[i] instanceof Promise)) {
        Promise.resolve(arr[i]).then(resolve, reject)
      } else {
        arr[i].then(resolve, reject)
      }
    }
  })
}

all方法接收一个数组。当数组中所有的promise的状态都达到resolved的时候,all方法的状态就会变成resolved,如果有一个状态变成了rejected,那么all方法的状态就会变成rejected

我们需要一个数组 res ,这个数组用来存放状态为 resolved 的结果。同时,我们还需要一个 count 变量,用来判断,当前数组是否执行完成。如果执行完成,那么就把这个 res 这个数组返回

Promise.all = function (arr) {
  return new Promise((resolve, reject) => {
    let res = [], count = 0;
    for (let i = 0; i < arr.length; i++) {
      if (!arr[i] instanceof Promise) {
        //
      } else {
        arr[i].then(
          (data) => {
            res[i] = data;
            if (++count === arr.length) {
              resolve(res);
            }
          },
          (err) => {
            reject(err);
          }
        );
      }
    }
  });
};

同时,我们对非 Promise 进行处理。

if (!arr[i] instanceof Promise) {
  res[i] = arr[i];
  if (++count === arr.length) {
    resolve(res);
  }
}

组合代码

Promise.all = function (arr) {
  return new Promise((resolve, reject) => {
    let res = [],
      count = 0;
    for (let i = 0; i < arr.length; i++) {
      if (!arr[i] instanceof Promise) {
        res[i] = arr[i];
        if (++count === arr.length) {
          resolve(res);
        }
      } else {
        arr[i].then(
          (data) => {
            res[i] = data;
            if (++count === arr.length) {
              resolve(res);
            }
          },
          (err) => {
            reject(err);
          }
        );
      }
    }
  });
};

Promise.any

框架抄下来,改个名字

Promise.any = function (arr) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arr.length; i++) {
      if (!(arr[i] instanceof Promise)) {
        Promise.resolve(arr[i]).then(resolve, reject)
      } else {
        arr[i].then(resolve, reject)
      }
    }
  })
}

Promise.any()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

和 all 方法刚好相反

Promise.all = function (arr) {
  return new Promise((resolve, reject) => {
    let res = [],
      count = 0;
    for (let i = 0; i < arr.length; i++) {
      if (!arr[i] instanceof Promise) {
        res[i] = arr[i];
        if (++count === arr.length) {
          resolve(res);
        }
      } else {
        arr[i].then(
          (data) => {
            res[i] = data;
            if (++count === arr.length) {
              resolve(res);
            }
          },
          (err) => {
            reject(err);
          }
        );
      }
    }
  });
};

Promise.allSettled

框架抄下来,改个名字

Promise.allSettled = function (arr) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arr.length; i++) {
      if (!(arr[i] instanceof Promise)) {
        Promise.resolve(arr[i]).then(resolve, reject)
      } else {
        arr[i].then(resolve, reject)
      }
    }
  })
}

Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。

Promise.allSettled 返回的是一个对象,在遍历数组的过程中,将这些信息都 push 到要返回的值中。

Promise.allSettled = function (arr) {
  return new Promise((resolve, reject) => {
    let res = [],
      count = 0;
    for (let i = 0; i < arr.length; i++) {
      if (!arr[i] instanceof Promise) {
        res[i] = arr[i];
        if (++count === arr.length) {
          resolve(res);
        }
      } else {
        arr[i]
          .then(
            (data) => {
              res[i] = {
                status: "fulfilled",
                value: data,
              };
            },
            (err) => {
              res[i] = {
                status: "rejected",
                value: err,
              };
            }
          )
      }
    }
  });
};

何时把这个数据返回呢?这个时候就要用到 finally 了。每次执行 .then 之后,都去判断一下,这个数组是否执行结束。

.finally(() => {
  if (++count === arr.length) {
    resolve(res);
  }
});

组装代码

Promise.allSettled = function (arr) {
  return new Promise((resolve, reject) => {
    let res = [],
      count = 0;
    for (let i = 0; i < arr.length; i++) {
      if (!arr[i] instanceof Promise) {
        res[i] = arr[i];
        if (++count === arr.length) {
          resolve(res);
        }
      } else {
        arr[i]
          .then(
            (data) => {
              res[i] = {
                status: "fulfilled",
                value: data,
              };
            },
            (err) => {
              res[i] = {
                status: "rejected",
                value: err,
              };
            }
          )
          .finally(() => {
            if (++count === arr.length) {
              resolve(res);
            }
          });
      }
    }
  });
};

更多文章,请看👉️:

如何快速记住手写数组方法的那些代码

如何快速记住手写发布/订阅模式的代码