实现Promise各种变体方法

183 阅读1分钟

听别人说是常考知识点,因此备注下。

1.Promise.finally

场景:无论promise执行成功或者失败的,都会走一下finally方法,做一下资源释放的工作。类似try catch finally。

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

2.Promise.each

场景:每个promise执行完成后,都执行调用一下

Promise.each = (promiseList) => {
  let p = new Promise((resolve, reject) => {
    for (const item of items) {
      item.then((r, j) => {
        resolve(r);
      });
    }
  })
  return p;
}

3.Promise.first

场景:一个页面当前正处于loading状态,同时请求了多个接口,无论哪个接口正确返回结果,则loading效果取消!或者其他的要获取获取第一个完成状态的值

Promise.first = (promiseList) => {
  return new Promise((resolve, reject) => {
    let i = 0;
    promiseList.forEach(p => {
      p.then(resolve).catch(() => {
        if (++i === promiseList.length) {
          reject('All promises not resolve')
        }
      });
    })
  })
}

4.Promise.last 

场景:与Promise.first对应的则是Promise.last,获取最后变成完成状态的值。这里与Promise.first不同的是, 只有最后一个Promise都变成最终态(完成或拒绝),才能知道哪个是最后一个完成的,这里我采用了计数的方式,then和catch只能二选一,等计数器达到list.length时,执行外部的resolve。

Promise.last = promiseList => {
  return new Promise((resolve, reject) => {
    let i = 0;
    let lastResult = null;
    const fn = () => {
      if (++i === promiseList.length) {
        lastResult === null ? reject('All promises not resolve') : resolve(lastResult);
      }
    }
    promiseList.forEach(p => {
      p.then(res => {
        lastResult = res;
        fn()
      }, () => {
        fn()
      });
    })
  })
}

5.Promise.none 

 场景:Promise.none与Promise.all正好相反,所有的promise都被拒绝了,则Promise.none变成完成状态。 该方法可以用Promise.first来切换,当执行Promise.first的catch时,则执行Promise.none中的resolve。

Promise.none = promiseList => {
  return new Promise((resolve, reject) => {
    let i = 0;
    let results = [];
    promiseList.forEach(p => {
      p.then(() => {
        reject('Some one resolved');
      }, (err) => {
        results.push(err.message);
        if (++i === promiseList.length) {
          resolve(results);
        }
      });
    })
  })
}

6.Promise.any 

 场景:Promise.any表示只获取所有的promise中进入完成状态的结果,被拒绝的则忽略掉。

Promise.any = promiseList => {
  return new Promise((resolve, reject) => {
    let i = 0;
    let results = [];
    let fn = () => {
      if (++i === promiseList.length) {
        resolve(results);
      }
    }
    promiseList.forEach(p => {
      p.then((res) => {
        results.push(res);
        fn();
      }, (err) => {
        fn();
      });
    })
  })
}