百行代码实现通过872条Promise/A+用例的Promise
点击上方 前端Q,关注公众号
回复加群,加入前端Q技术交流群
一直听说想成为一名高级前端程序员需要理解一些源码,那就从 Promise 开始吧,作者尽量用最少的语言让你理解 Promise
准备
Promises/A+原文[2]
Promises/A+译文[3]
安装 Promise 测试工具
npm i promises-aplus-tests -g
复制代码
运行测试工具,检测 Promise 是否符合规范
promises-aplus-tests [promise文件名]
复制代码
完整代码先过用例
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
    this.state = PENDING;
    this.value = null;
    this.reason = null;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];
    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = FULFILLED;
        this.value = value;
        this.onFulfilledCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (e) {
      this.reject(e);
    }
  }
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    let promise2 = new Promise((resolve, reject) => {
      if (this.state === FULFILLED) {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      if (this.state === REJECTED) {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });
      }
    });
    return promise2;
  }
}
const resolvePromise = (promise2, x, resolve, reject) => {
  if (promise2 === x)
    return reject(
      new TypeError('Chaining cycle detected for promise #' )
    );
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    let called;
    try {
      const then = x.then;
      if (typeof then !== 'function') resolve(x);
      else {
        then.call(
          x,
          (value) => {
            if (called) return;
            called = true;
            resolvePromise(promise2, value, resolve, reject);
          },
          (reason) => {
            if (called) return;
            called = true;
            reject(reason);
          }
        );
      }
    } catch (err) {
      if (called) return;
      called = true;
      reject(err);
    }
  } else {
    resolve(x);
  }
};
Promise.defer = Promise.deferred = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};
module.exports = Promise;
复制代码
完整代码127行,增加 Promise 测试代码一共 136 行代码。
如何测试
在 VS Code 新建文件 promise.jspromise.jspromise.js 文件
// promise代码
class Promise {
  constructor() {}
  then() {}
  catch() {}
}
// 测试代码
Promise.defer = Promise.deferred = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};
module.exports = Promise;
复制代码
在 promise.jspromise.jspromise.js 文件所在目录打开终端,输入下面命令即可测试 Promise 是否符合规范
promises-aplus-tests promise.js
复制代码
后续讲解,不再解释测试代码,只讨论 Promise 代码了
请紧跟思路,本篇文章核心开始了
声明 Promise 类
Promise 常用的有 then 方法 和 catch,先用 ES6 语法声明一个 Promise 类
这点不难理解吧?
class Promise {
  constructor() {}
  then() {}
  catch() {}
}
复制代码
constructor
正常使用 Promise 一般 如下图所示, new Promise(参数是一个函数)
let p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});
复制代码
所以 在 Promise 类的 constructor 使用 executor 形参接收这个参数,这点不难理解吧?
class Promise {
  constructor(executor) {}
  then() {}
  catch() {}
}
复制代码
继续:
executor 是用户输入的参数,咱们不能相信用户一定会使用一个函数作为 new Promise(参数) 对不对?
所以这里就需要判断一下 executor 是否是一个函数。
很好理解吧?
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
  }
  then() {}
  catch() {}
}
复制代码
executor
constructor 这节已经知道 executor 是个函数了,executor 函数也是有参数的呀。
如下 Promise 使用代码
let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random() > 0.5 ? resolve('正确') : reject('错误');
  }, 1000);
});
p1.then((value) => {
  console.log(value);
});
复制代码

Promises/A+ 规范中说:resolve 是进行成功的一系列操作,reject 是失败的一些操作,还有成功原因,失败原因?这些咱们的 Promise 都要有,都加上
resolve 和 reject
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
    // promise 被解决时传递给解决回调的值
    this.value = null;
    // promise 被拒绝时传递给解决回调的值
    this.reason = null;
    // 成功的一系列操作
    const resolve = () => {};
    //失败的一些操作
    const reject = () => {};
    executor(resolve, reject);
  }
  then() {}
  catch() {}
}
复制代码
状态
Promises/A+译文[4]

Promises/A+ 规范中说,Promise 要有 3 种状态。咱们在代码中将这三种状态加上,这很好理解吧
常量命名用大写,这点可以理解的
PENDING 、FULFILLED 和 REJECTED
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
  }
  then() {}
  catch() {}
}
复制代码
要求说,Pending 状态只能去 Fulfilled 或者 Rejected 且不可变,这就需要一个变量记录 Promise 状态值, 并且状态值初始值为 Pending 这点可以理解吧
this.state
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
    this.state = PENDING;
    this.value = null;
    this.reason = null;
    const resolve = () => {};
    const reject = () => {};
    executor(resolve, reject);
  }
  then() {}
  catch() {}
}
复制代码
Pending 状态只能去 Fulfilled 或者 Rejected 意味着 resolve 和 reject 只有在 Pending 可以执行,没问题吧。
所以需要在 resolve 和 reject 函数中加判断
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
    this.state = PENDING;
    this.value = null;
    this.reason = null;
    const resolve = () => {
      // PENDING状态才能执行,执行完成修改状态为FULFILLED
      if (this.state === PENDING) {
        this.state = FULFILLED;
      }
    };
    const reject = () => {
      // PENDING状态才能执行,执行完成修改状态为 REJECTED
      if (this.state === PENDING) {
        this.state = REJECTED;
      }
    };
    executor(resolve, reject);
  }
  then() {}
  catch() {}
}
复制代码
执行完成功或者异常函数是不是要有成功或者异常数据呀,这些回调的值是不是需要保存到类中,在 then 方法中返回?
添加上
value 和 reason
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
    this.state = PENDING;
    this.value = null;
    this.reason = null;
    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = FULFILLED;
        // 解决时传递给解决回调的值
        this.value = value;
      }
    };
    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        // 拒绝时传递给解决回调的值
        this.reason = reason;
      }
    };
    executor(resolve, reject);
  }
  then() {}
  catch() {}
}
复制代码
constructor 这就完成了吗?不,还差一步。
executor 是个函数,这在上文中有描述,但是函数有没有可能执行错误,直接执行这个函数报错,报错怎么处理?try/catch 大法喽
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
    this.state = PENDING;
    this.value = null;
    this.reason = null;
    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = FULFILLED;
        // 解决时传递给解决回调的值
        this.value = value;
      }
    };
    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        // 拒绝时传递给解决回调的值
        this.reason = reason;
      }
    };
    try {
      // 如果函数顺利执行,执行函数
      executor(resolve, reject);
    } catch (error) {
      // 函数抛出异常,将异常信息通过 reject 返回
      reject(error);
    }
  }
  then() {}
  catch() {}
}
复制代码
Then
单独写 then 这个函数,暂时忽略 constructor 代码吧。代码太多容易混淆。读者觉得呢?
then() {}
复制代码
Promises/A+译文[5]

根据规范中规定 then 要有两个参数,并且这两个参数需要是函数,如果不是函数需要忽略
所以 then 代码如下;不难理解吧
then(onFulfilled, onRejected){
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
}
复制代码
onFulfilled 和 onRejected
接着看规范描述

onFulfilled和onRejected调用次数不可超过一次,
then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    // 只执行一次
    if (this.state === Promise.FULFILLED) {
      onFulfilled(this.value);
    }
    if (this.state === Promise.REJECTED) {
      onRejected(this.reason);
    }
  }
复制代码
resolve 支持异步
这样就可以了吗??不不不
如果 Promise 中 resolve 是在异步函数中执行的,目前我写的 Promise 代码中 console 并不会执行。
let p2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(2);
  }, 1000);
});
p2.then((value) => {
  console.log(value);
});
复制代码
原因是执行 .then函数的时候 Promise 状态是 Pending ,当前我在 Promise.then方法中只写了 状态为 FULFILLED 和 REJECTED 的处理
所以.then函数还要处理状态位PENDING 的处理,pending 状态下,将.then 函数的入参先放在数组中,在异步执行 resolve 是调用
还有问题吗?
有的
then异步
console.log(1);
let p2 = new Promise((resolve) => {
  resolve(4);
  console.log(2);
});
p2.then((value) => {
  console.log(value);
});
console.log(3);
//  1,2,3,4
复制代码
正常返回 1,2,3,4 现在我写的 promise 返回 1、2、4、3
什么原因呢?原因是 .then 中的函数立即执行了,这不符合标准呀,解决办法是给 .then 函数添加 setTimeout 模拟异步
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    if (this.state === FULFILLED) {
      setTimeout(() => {
        onFulfilled(this.value);
      });
    }
    if (this.state === REJECTED) {
      setTimeout(() => {
        onRejected(this.reason);
      });
    }
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          onFulfilled(this.value);
        });
      });
      this.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          onRejected(this.reason);
        });
      });
    }
    let promise2 = new Promise(() => {});
    return promise2;
  }
}
复制代码
Promise 的数组需要在 constructor 中声明,并且在 resolve 中执行,所以代码 Promise 到这里全部代码如下:
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
  constructor(executor) {
    if (typeof executor !== 'function') {
      return new TypeError(`Promise resolver ${executor} is not a function`);
    }
    this.state = PENDING;
    this.value = null;
    this.reason = null;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];
    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = FULFILLED;
        this.value = value;
        this.onFulfilledCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (e) {
      this.reject(e);
    }
  }
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    if (this.state === FULFILLED) {
      setTimeout(() => {
        onFulfilled(this.value);
      });
    }
    if (this.state === REJECTED) {
      setTimeout(() => {
        onRejected(this.reason);
      });
    }
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          onFulfilled(this.value);
        });
      });
      this.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          onRejected(this.reason);
        });
      });
    }
  }
}
复制代码
写到这里,我去测试了一下显示有 806 个异常;也就是说通过了 66 个测试用例。继续努力
then如何返回一个新的Promise
接着看规范描述: 
then  方法必须返回一个  promise  对象
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    if (this.state === FULFILLED) {
      setTimeout(() => {
        onFulfilled(this.value);
      });
    }
    if (this.state === REJECTED) {
      setTimeout(() => {
        onRejected(this.reason);
      });
    }
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          onFulfilled(this.value);
        });
      });
      this.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          onRejected(this.reason);
        });
      });
    }
    // 返回一个新的 promise 对象
    let promise2 = new Promise(() => {});
    return promise2;
  }
复制代码
可以理解吧?每次 .then 都返回一个新的 promise 对象,.then 方法是不是就可以一直调用下去了
这里为什么不可以直接返回 this,比如 jQuery 不就是直接返回 this 实现链式调用的吗?
因为 promise 有 3 种状态,且状态不可逆,所以必须返回一个新的 promise 对象
then返回Promise解决过程
接着看规范描述:
如果 onFulfilled或者onRejected返回一个值x,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)如果 onFulfilled或者onRejected抛出一个异常e,则promise2必须拒绝执行,并返回拒因e如果 onFulfilled不是函数且promise1成功执行,promise2必须成功执行并返回相同的值如果 onRejected不是函数且promise1拒绝执行,promise2必须拒绝执行并返回相同的据因
第一句
需要确定, onFulfilled  或者  onRejected  返回一个值  x要执行 Promise2
修改 then 代码如下:
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    let promise2 = new Promise((resolve, reject) => {
      if (this.state === FULFILLED) {
        setTimeout(() => {
         const x = onFulfilled(this.value);
        });
      }
      if (this.state === REJECTED) {
        setTimeout(() => {
          const x = onRejected(this.reason);
        });
      }
      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
           const x =  onFulfilled(this.value);
          });
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
           const x =  onRejected(this.reason);
          });
        });
      }
    });
    return promise2;
  }
}
复制代码
第二句
如果  onFulfilled  或者  onRejected  抛出一个异常  e ,则  promise2  必须拒绝执行,并返回拒因  e
使用 try/catch 捕捉  onFulfilled  或者  onRejected 抛出的异常
then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    let promise2 = new Promise((resolve, reject) => {
      if (this.state === FULFILLED) {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.state === REJECTED) {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
            } catch (error) {
              reject(error);
            }
          });
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
            } catch (error) {
              reject(error);
            }
          });
        });
      }
    });
    return promise2;
  }
复制代码
第三句
如果  onFulfilled  不是函数且  promise1  成功执行, promise2  必须成功执行并返回相同的值
promise2 执行成功并返回值,这句简单,在返回 x 的地方直接 resolve(x) 不就可以了吗?
then(onFulfilled, onRejected) {
  if (typeof onFulfilled !== 'function') {
    onFulfilled = (value) => value;
  }
  if (typeof onRejected !== 'function') {
    onRejected = (err) => {
      throw err;
    };
  }
  let promise2 = new Promise((resolve, reject) => {
    if (this.state === FULFILLED) {
      setTimeout(() => {
        try {
          const x = onFulfilled(this.value);
          resolve(x);
        } catch (error) {
          reject(error);
        }
      });
    }
    if (this.state === REJECTED) {
      setTimeout(() => {
        try {
          const x = onRejected(this.reason);
          // 这里直接 resolve 并并且返回 x
          resolve(x);
        } catch (error) {
          reject(error);
        }
      });
    }
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolve(x);
          } catch (error) {
            reject(error);
          }
        });
      });
      this.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolve(x);
          } catch (error) {
            reject(error);
          }
        });
      });
    }
  });
  return promise2;
}
复制代码
如果 x 是基本数据类型可以,考虑一下,如果 x 是引用数据类型,是函数,甚至是 Promise 呢?
所以这里需要对 x 的数据类型判断
既然自成一体,索性增加一个方法执行这些 x 值
方法名为:resolvePromise
 then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== 'function') {
      onFulfilled = (value) => value;
    }
    if (typeof onRejected !== 'function') {
      onRejected = (err) => {
        throw err;
      };
    }
    let promise2 = new Promise((resolve, reject) => {
      if (this.state === FULFILLED) {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.state === REJECTED) {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          });
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          });
        });
      }
    });
    return promise2;
  }
  function resolvePromise(promise2, x, resolve, reject){
  }
复制代码
resolvePromise
接下来开始写 resolvePromise 这个函数
判断 x 只不是 promise 自己
promise 不能循环调用,
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(
      new TypeError('Chaining cycle detected for promise #' )
    );
  }
}
复制代码
判断 x 是不是引用数据类型
如果不是引用数据类型,直接执行 resolve(x)
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(
      new TypeError('Chaining cycle detected for promise #' )
    );
  }
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
  } else {
    resolve(x);
  }
}
复制代码
如果是引用数据类型,判断数据中是否有 then 这个属性,如果有 then 不是函数,直接执行 resolve(x)
这里解释一下:如果 then 是函数,表示 x 可能是 Promise 对象,需要特殊处理,如果不是函数,当作一般对象处理
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(
      new TypeError('Chaining cycle detected for promise #' )
    );
  }
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    const then = x.then;
    if (typeof then !== 'function') {
      resolve(x);
    } else {
    }
  } else {
    resolve(x);
  }
}
复制代码
当然,只要是代码就有可能出现异常,所以这里需要 try/catch 捕捉一些可能的异常
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(
      new TypeError('Chaining cycle detected for promise #' )
    );
  }
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    try {
      const then = x.then;
      if (typeof then !== 'function') {
        resolve(x);
      } else {
      }
    } catch (err) {
      reject(err);
    }
  } else {
    resolve(x);
  }
}
复制代码
如果 then 是函数
then 是函数,执行 then。因为此时的 then 是从 x 上获取的,所以要调用 call 方法将 then 函数的 this 重新指向 x
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(
      new TypeError('Chaining cycle detected for promise #' )
    );
  }
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    try {
      const then = x.then;
      if (typeof then !== 'function') {
        resolve(x);
      } else {
        then.call(
          x,
          (value) => {
            resolvePromise(promise2, value, resolve, reject);
          },
          (reason) => {
            reject(reason);
          }
        );
      }
    } catch (err) {
      reject(err);
    }
  } else {
    resolve(x);
  }
}
复制代码
上述代码基本完成了 Promise 的功能,但是还有一点规范文档上说:
如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
这需要增加标识位 calledcalledcalled , called为true直接返回,
const resolvePromise = (promise2, x, resolve, reject) => {
  if (promise2 === x)
    return reject(
      new TypeError('Chaining cycle detected for promise #' )
    );
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    let called;
    try {
      const then = x.then;
      if (typeof then !== 'function') resolve(x);
      else {
        then.call(
          x,
          (value) => {
            if (called) return;
            called = true;
            resolvePromise(promise2, value, resolve, reject);
          },
          (reason) => {
            if (called) return;
            called = true;
            reject(reason);
          }
        );
      }
    } catch (err) {
      if (called) return;
      called = true;
      reject(err);
    }
  } else {
    resolve(x);
  }
};
复制代码
结语
虽然我想用尽量少的语言去描述或者讲解这个 Promise 。但是最后依然用了将近4000字描述这个东西是什么。作者目前水平有限,只得尽量将 Promise 描述清楚。如有任何意见和建议欢迎评论区留言讨论。
关于本文
作者:北斗落凡尘
https://juejin.cn/post/7065693195799265287

往期推荐



最后
欢迎加我微信,拉你进技术群,长期交流学习...
欢迎关注「前端Q」,认真学前端,做个专业的技术人...


