关于Promise/A+(二)

351 阅读3分钟

之前的文章介绍了什么是Promise,它是一种更加现代解决JS异步编程的解决方案.现在我们通过了解Promise A+规范,来自己尝试实现一个简单的Promise,加深对它的理解.

一. Promise A+规范

  1. promise:是一个拥有 then 方法的对象或函数,其行为符合本规范
  2. thenable:是一个定义了 then 方法的对象或函数。这个主要是用来兼容一些老的Promise实现,只要一个Promise实现是thenable,也就是拥有then方法的,就可以跟Promises/A+兼容。
  3. value:指reslove出来的值,可以是任何合法的JS值(包括 undefined , tenablepromise等)
  4. exception:异常,在Promise里面用throw抛出来的值
  5. reason:拒绝原因,是reject里面传的参数,表示reject的原因
  6. promise必须有三种状态pendingfulfilledrejected
  7. thenpromise必须提供一个then方法来访问其当前或最终的valuereason,then方法接受两个参数onFulfilledonRejected

详细Promise/A+规范

MDN about Promise

二. 手写Pormise

tip1: 我们在调用promise构造函数时,在合适时机根据状态情况来分别调用executor的两个参数reslovereject,经过他们的处理后的值,可以在then方法中通过它的两个函数参数获取,resolve的处理后的值在onfulfilled中获取,reject处理后的值则在onrejected中拿到。

tip2: Promise实例的状态只能从pending变为fuilfilled,或从pending变为rejected,状态一旦变更就无法再次变化

tip3:Promise的链式调用,是通过then方法的onfulfilled和onrejected支持返回一个Promise实例或普通值,而且返回的这个Promise实例或普通值将会传给下一个then方法的onfulfilled和onrejected函数

// 首先来创建骨架
function Promise(executor) {
// 因为状态的不可变,需要存储状态
// 用两个值分别存储`resolve`和`reject`处理后的值
  this.status = "pending";
  this.value = null;
  this.reason = null;
// 让resolve可以支持异步,我们要把onfulfilled方法在pending时存起来,在resolve中执行,来实现异步
// 为了支持多个then方法,所以将它们都存起来,依次调用
  this.onFulfilledArray = [];
  this.onRejectedArray = [];

// 作为executor的参数给开发者使用,下同
  const resolve = (value) => {
  // 这里通过setTimeout来保证异步执行,但是Promise属于微任务,所以这里是不严谨的
    setTimeout(() => {
      if (this.status === "pending") {
        this.value = value;
        // 保证状态只能从pending变化一次
        this.status = "fulfilled";

        this.onFulfilledArray.forEach((func) => {
          func(value);
        });
      }
    });
  };

  const reject = (reason) => {
    setTimeout(() => {
      if (this.status === "pending") {
        this.reason = reason;
        this.status = "rejected";

        this.onRejectedArray.forEach((func) => {
          func(reason);
        });
      }
    });
  };

// 捕获构造函数的错误,并触发Promise实例的状态改变
  try {
    executor(resolve, reject);
  } catch (error) {
    reject(error);
  }
}

Promise.prototype.then = function (onfulfilled, onrejected) {
// 作为then方法的返回值
  let promise2;

  if (this.status === "fulfilled") {
    return promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        try {
        // 新promise2经过resolved处理后的值为onfulfilled的执行结果,下同
          let result = onfulfilled(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      });
    });
  }

  if (this.status === "rejected") {
    return promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        try {
          let result = onrejected(this.reason);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      });
    });
  }

  if (this.status === "pending") {
    return promise2 = new Promise((resolve, reject) => {
    /**
    * Promise调用then方法后应该返回的Promise,就是这里的Promise2
    * Promise2应该在异步处理结束后,在依次执行onFulfilledArray和onRejectedArray数组中的函数时被决议
    * 同时数组中的函数还应该确定promise2的状态并决议
    * 下同
    */
      this.onFulfilledArray.push(() => {
        try {
          let result = onfulfilled(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      });

      this.onRejectedArray.push(() => {
        try {
          let result = onrejected(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      });
    });
  }
};

尾言

至此,我们已经基本实现了一个Promise,保证了它的状态不可逆,支持链式调用、完成了then方法。为了实现一份较为完整了Promise,我还是参考、学习了很多相关内容,希望我写的这些,可以为大家提供一些帮助。后续我还会继续深入关于规范中关于The Promise Resolution Procedure的部分,有兴趣的同学,可以一起讨论学习。