javascript 实现Promise.resolve/reject

实现Promise.resolve/reject

这两个方法直接挂载在Promise对象身上,用于快速指定一个带有预定状态的Promise实例,由于它们的实现简单且极其相似,我将它们直接放在这里一起带过。

不过,在实现之前,有一点需要注意的细节,请观察下方的代码,并思考执行结果:

Promise.resolve(Promise.reject(1)).then(
  (v) => {
    console.log(0);
  },
  (e) => {
    console.log(e);
  }
);

Promise.reject(Promise.resolve(1)).then(
  (v) => {
    console.log(0);
  },
  (e) => {
    console.log(e);
  }
);

正确答案是:1状态为resolved的Promise实例,看到了吗,这两个函数的执行逻辑有一些不同:如果resolve方法的参数是一个Promise实例,那么resolve方法会根据这个Promise实例的执行结果来改变状态;而reject方法则会直接将参数作为失败的拒因抛出。

其实很好理解,期待百分百的成功往往不现实,但期待百分百的失败倒是信手拈来。

MyPromise.resolve = function (value) {
  return new MyPromise((resolve, reject) => {
    if (value instanceof MyPromise) {
      value.then(resolve, reject);
    } else {
      resolve(value);
    }
  });
 };

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

实现Promise.all

Promise.all的实现同样不复杂,但是有一些小细节需要注意。该方法用于执行多个Promise代码,并返回一个新的Promise,这个Promise会根据所有的异步程序执行结束后返回相应的结果来改变状态:

  1. 如果全部执行成功,则resolve,并按照执行的顺序返回一个终值数组;
  2. 只要有一个执行失败,则立即reject,并返回当前失败的拒因。

根据要求,我们开始码实现:

MyPromise.all = function (promises) {
  return new MyPromise((resolve, reject) => {
    let successfulPromiseArr = [],
      successfulCount = 0; // 用于存在成功完成执行的Promise结果和数量

    promises.forEach((promise, index) => {
      if (!(promise instanceof MyPromise)) {
        successfulPromiseArr[index] = promise;

        successfulCount++;
      }

      promise.then(
        (value) => {
          successfulPromiseArr[index] = value;

          successfulCount++;

          if (successfulCount === promises.length) {
            resolve(successfulPromiseArr);
          }
        },
        (reason) => {
          reject(reason);
        }
      );
    });
  });
};

从上面的源码实现中,可以提取出几点关于实现时需要注意的小细节:

  1. 如果传入的数组中包含非Promise实例对象的数据类型,则直接将其作为终值加入返回数组;
  2. 因为要按照执行的顺序返回终值,且由于异步代码完成顺序不确定,所以不能使用push方法,而是使用脚标的方式进行设置;
  3. 原因同第二点,在判断当前完成的Promise是否为最后一个时不能通过判断数组脚标的方式,上面代码使用了一个变量来进行计数,当完成的数量达到了数组的数量时,再进行resolve。

实现Promise.race

Promise.race相比Promise.all来说,逻辑简单了许多,只需要根据第一个完成执行的Promise对象的结果来决定返回状态,同时注意处理传入非Promise实例对象类型数据的情况即可。

MyPromise.race = function (promises) {
  return new MyPromise((resolve, reject) => {
    promises.forEach((promise, index) => {
      if (!(promise instanceof MyPromise)) {
        resolve(promise);
      }

      promise.then(
        (value) => {
          resolve(value);
        },
        (reason) => {
          reject(reason);
        }
      );
    });
  });
};

实现Promise.prototype.finally

最后我们再来实现一下这个方法,这个方法实现起来是最简单的一个,它的执行逻辑也非常简单:这个方法无论上一个Promise的返回状态如何,都会执行回调函数中的内容。

MyPromise.prototype.finally = function (callback) {
  return this.then(
    value => {
      callback();
      ,kreturn value;
    },
    reason => {
      callback();
      throw reason;
    }
  );
};

Promise的缺点

  1. promise一旦新建,就会立即执行,无法取消
  2. 如果不设置回掉函数,promise内部抛出的错误就不会反应到外部
  3. 处于pending状态时,是不能知道目前进展到哪个阶段的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值