最近看到好多讲解Promise源码解析,或者自己实现一个Promise的文章,突然想自己造个轮子试一试。

先说明一下,该轮子并不完全遵守任何标准和规范,只是对正规Promise使用后的理解和感受而编写的,纯属兴趣研究。

下面是实现代码:

// 对象类型判断const is = (typeAsString) => obj => Object.prototype.toString.call(obj) === typeAsString// 判断是否为一个Error对象const isError = is('[object Error]')/** * 自定义Promise对象 * @param {(resolve: (value: any) => void, reject: (reason: any) => void) => void} executor  */function MyPromise(executor) {  this.executor = executor  // 初始状态为pending...  this.status = 'pending'  /**   * 内部判定状态,只有处于pending状态才可继续执行   * @param {number} value    */  function resolve(value) {    if (this.status === 'pending') { // 确保只执行一次      this.onfulfilled = ___onfulfilled.call(this, value)    }  }  /**   * 为了缓存resolve方法的执行结果   * @param {*} value value就是resolve方法的执行结果   */  function ___onfulfilled(value) {    this.status = 'fulfilled'   // 更改内部状态    /**     * @param {(value: number) => void} onfulfilled 这里是then方法中传入的参数     */    return (onfulfilled) => {      return onfulfilled(value) //     }  }  /**   * 触发异常的方法   * @param {string} reason    */  function reject(reason) {    if (this.status === 'pending') {  // 确保只执行一次      this.onrejected = ___onrejected.call(this, reason)    }  }  /**   *    * @param {Error} reason 如果传入的不是一个Error对象,那么会使用Error包装一下   */  function ___onrejected(reason) {    this.status = 'rejected'    // 更改内部状态    return (onrejected) => {      reason = isError(reason) ? reason : new Error(reason)      return onrejected(reason)    }  }  /**   * @param {(value: number) => any} onfulfilled 处理成功的函数   * @param {(reason: any) => void} onrejected 处理出现异常的函数,如果传入该参数,那么catch方法就捕获不到了   */  this.then = function(onfulfilled, onrejected) {    const self = this    return new MyPromise((resolve, reject) => {      setTimeout(function waitStatus() {        switch (self.status){          case 'fulfilled': // resolved            if (onfulfilled) {              // 将onfulfilled方法的返回值交给resolve,确保下一个.then方法能够得到上一个.then方法的返回值              const nextValue = self.onfulfilled(onfulfilled)               resolve(nextValue)            } else {              resolve()   // 没有传入参数,假装传入了参数:)            }            break          case 'rejected':  // rejected            if (!onrejected) { // 如果没有传递onrejected参数,默认实现一个,确保catch方法能够捕获到              onrejected = (reason) => reason            }            const nextReject = self.onrejected(onrejected)            reject(nextReject)            break          case 'pending':   //           default:              setTimeout(waitStatus, 0) // 只要是pending状态,继续等待,直到不是pending              break        }      }, 0);    })  }  /**   * 捕获异常   * @param {(reason: any) => void} onrejected   */  this.catch = function(onrejected) {    const self = this    setTimeout(function reject() {      if (self.status === 'rejected') {        self.onrejected(onrejected)      } else {        setTimeout(reject, 0);      }    }, 0);  }  // 直接执行  this.executor(resolve.bind(this), reject.bind(this));}

目前不考虑参数传入的正确性,假设传入的参数全部是正确的情况下,在nodejs环境下能够正常运行。以下是测试代码:

// 覆盖nodejs环境中默认的Promise对象global.Promise = MyPromiseasync function test () {  const r = await new Promise((resolve) => {    setTimeout(() => {      resolve(121)    }, 1000);  })  console.log(r)    // 打印121}test()

以上代码主要是使用setTimeout方法去检查Promise对象内部的状态,一旦发生变化立即作出相应的处理。源代码在此。欢迎拍砖。

谢谢观看!