手写Promise核心原理(三)

177 阅读3分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

前面写了 Promise的入门和相关方法的使用,  Promise的关键问题,  手写Promise核心原理(一)手写Promise核心原理(二), 需要的童鞋请移步。这篇文章写下Promise相关方法的核心原理:

  1. 手写Promise.resolve(value)
  2. 手写Promise.reject(reason)
  3. 手写Promise.all(promises)
  4. 手写Promise.race(promises)

一、手写Promise.resolve(value)

Promise.resolve()是将现有对象转为 Promise 对象,所以需要在最外层返回一个新的Promise实例。 resolve方法接受的参数value分为两种,对应不同的操作如下:

  • 当value为Promise实例或者value有then方法时,返回value.then的执行结果。因为当value为Promise实例时,若想得到其返回值,则需要调用其then方法;当value不为Promise实例但却有then方法时,立即执行then方法并返回结果。
  • 其他时候返回该value。
Promise1.resolve = function(value) {
  return new Promise1(function(resolve, reject) {
    if (value instanceof Promise1 || value.then) {
      value.then(resolve, reject);
    } else {
      resolve(value);
    }
  });
};

二、手写Promise.reject(reason)

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。 所以代码很简单,返回一个Promise,其中直接将错误原因reject出去就行。

Promise1.reject = function(reason) {
  return new Promise1(function(resolve, reject) {
    reject(reason);
  });
};

三、手写Promise.all(promises)

all方法的特点:

  • all方法接受一个具有Iterator接口的数据,其中若不为promise的元素将被转化为promise。

  • 当所有promise实例的状态都变为fulfilled时,all方法返回一个包含所有Promise实例返回结果的数组;当有一个promise实例的状态都变为rejected时,all方法返回该pomise实例的返回结果。

all方法内部的操作:

  1. 返回一个新的Promise实例。
  2. 预先准备一个数组values,存储所有成功的promise的返回值。设置一个计数器resolveCount来计算成功promise的个数,可以用来判断是否所有promise都执行成功。
  3. 遍历参数promises,
  • 若其中元素不为promsie实例则变为promise实例,前面讲了Promise.resolve()方法便是将现有对象转化为promised对象。

  • 对每个元素执行then操作,当失败时则直接reject,当成功时将计数器加1并将返回值插入到values数组中,当所有promise都执行成功时,将成功的返回值组成的数组values resolve出去。

Promise1.all = function(promises) {
  var _this = this;
  return new Promise1(function(resolve, reject) {
    var values = new Array(promises.length);
    var resolveCount = 0;
    promises.forEach(function(promiseItem, index) {
      if (!(promiseItem instanceof Promise1)) {
        promiseItem = _this.resolve(promiseItem);
      }
      promiseItem.then(
        function(value) {
          resolveCount++;
          values[index] = value;
          if (resolveCount == promises.length) {
            resolve(values);
          }
        },
        function(reason) {
          reject(reason);
        }
      );
    });
  });
};

四、手写Promise.race(promises)

race方法的特点:

  • race方法接收的参数与all方法一样,都是接收一个具有Iterator接口的数据,其中若不为promise的元素将被转化为promise。

  • race方法的返回结果为先执行完的第一个promsie实例的返回结果。

race方法内部的操作:

  1. 返回一个新的Promise实例。
  2. 遍历参数promises,
  • 若其中元素不为promsie实例则变为promise实例,前面讲了Promise.resolve()方法便是将现有对象转化为promised对象。
  • 对每个元素执行then操作,并直接将结果resolve或reject出去。此时无论哪一个promise先执行完成,将结果返回出去了,后面的promise都无法再改变状态了。
Promise1.race = function(promises) {
  var _this = this;
  return new Promise(function(resolve, reject) {
    promises.forEach(function(promiseItem) {
      if (!(promiseItem instanceof Promise1)) {
        promiseItem = _this.resolve(promiseItem);
      }
      promiseItem.then(
        function(value) {
          resolve(value);
        },
        function(reason) {
          reject(reason);
        }
      );
    });
  });
};