通俗解说之手写Promise.all和Promise.race

113 阅读2分钟

对于promise,手写相关api常用于考察对于promise的理解深度,Promise.all和Promise.race就是其中经常考察的api之一。本文主要使用通俗易懂的语言解说,应如何轻松的实现这两个api。


关于返回值

这两个api都返回一个新的promise,因此我们可以使用new创建一个promise,并返回:

Promise.all = function (promises) {
  return new Promise((resolve,reject)=>{});
}

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

如果传入的不是可迭代对象

这两个都要求传入的参数是可迭代对象,如果不是,则应抛出一个错误:

Promise.all = function (promises) {
  if(typeof promises?.[Symbol.iterator] !== 'function') {
    throw new Error('TypeError: param is not iterable');
  }
  return new Promise((resolve,reject)=>{});
}

Promise.race = function (promises) {
  if(typeof promises?.[Symbol.iterator] !== 'function') {
    throw new Error('TypeError: param is not iterable');
  }
  return new Promise((resolve,reject)=>{});
}

如果传入的数组为空

这两个api对于数组为空的处理大不相同:

  • Promise.all: 立即返回一个包含所有兑现值的数组,即空数组。
  • Promise.race: 如果传入的 iterable 为空,返回的 promise 就会一直保持待定状态。不调用resolve和reject,只调用return即为这种效果。

综上,可为:

Promise.all = function (promises) {
  if(typeof param?.[Symbol.iterator] === 'function') {
    throw new Error('TypeError: param is not iterable');
  }
  return new Promise((resolve,reject)=>{
    const len = promises.length;
    if(len === 0){
      resolve([]);
    } else {
    }
  });
}

Promise.race = function (promises) {
  if(typeof param?.[Symbol.iterator] === 'function') {
    throw new Error('TypeError: param is not iterable');
  }
  return new Promise((resolve,reject)=>{
    const len = promises.length;
    if(len === 0) {
      return;
    } else {
    }
  });
}

主体逻辑

下面是主体逻辑:

  • Promise.all: 等待所有兑现(或第一个拒绝)的结果,并存储在结果数组中返回。
  • Promise.race: 随着第一个 promise 的敲定而敲定。
Promise.all = function (promises) {
  if(typeof param?.[Symbol.iterator] === 'function') {
    throw new Error('TypeError: param is not iterable');
  }
  return new Promise((resolve,reject)=>{
    const len = promises.length;
    let result = [];
    let index = 0;
    if(len === 0){
      resolve([]);
    } else {
      for(let i = 0; i < len; i++ ) {
        Promise.resolve(promises[i]).then((data) => {
          index++;
          result[i] = data;
          if(index === len) {
            resolve(result);
          }
        },err => {
          reject(err);
        })
      }
    }
  });
}

Promise.race = function (promises) {
  if(typeof param?.[Symbol.iterator] === 'function') {
    throw new Error('TypeError: param is not iterable');
  }
  return new Promise((resolve,reject)=>{
    const len = promises.length;
    if(len === 0) {
      return;
    } else {
      for(let i = 0; i < len; i++ ) {
        Promise.resolve(promises[i]).then((data) => {
          resove(data);
        },err => {
          reject(err);
        })
      }
    }
  });
}

全文完。