Promise 和 Promise/A+ 规范

Promise详解与实现(Promise/A+规范) - 简书 (jianshu.com)

简易版 Promise 实现

class Promise {
  constructor(executor) {
    this.state = "pending";
    this.value = undefined;
    this.reason = undefined;

    let resolve = (value) => {
      if (this.state === "pending") {
        this.state = "resolved";
        this.value = value;
      }
    };

    let reject = (reason) => {
      if (this.state === "pending") {
        this.state = "rejected";
        this.reason = reason;
      }
    };

    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onResolved, onRejected) {
    if (this.state === "resolved") {
      onResolved(this.value);
    }

    if (this.state === "rejected") {
      onRejected(this.reason);
    }
  }
}

Promise/A+ 规范要点

补充:Promise/A+ 规范定义了一个 thenable 必须满足的契约,面试常考点:

  • 状态机必须是 pending → fulfilled 或 pending → rejected,状态一旦确定不可再变;
  • then 的两个参数 onFulfilled、onRejected 都是可选的,缺省时透传值/异常;
  • 同一个 promise 上的 then 必须按注册顺序依次执行;
  • then 必须返回一个新的 promise,支持链式调用;
  • onFulfilled / onRejected 必须异步执行(推到微任务队列)。

满足 A+ 规范的最小实现(异步版)

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

function Promise(executor) {
  this.state = PENDING;
  this.value = undefined;
  this.reason = undefined;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  const resolve = (value) => {
    if (this.state === PENDING) {
      this.state = FULFILLED;
      this.value = value;
      this.onFulfilledCallbacks.forEach((cb) => cb());
    }
  };
  const reject = (reason) => {
    if (this.state === PENDING) {
      this.state = REJECTED;
      this.reason = reason;
      this.onRejectedCallbacks.forEach((cb) => cb());
    }
  };

  try {
    executor(resolve, reject);
  } catch (err) {
    reject(err);
  }
}

Promise.prototype.then = function (onFulfilled, onRejected) {
  return new Promise((resolve, reject) => {
    const handleFulfilled = () =>
      queueMicrotask(() => {
        try {
          const x = onFulfilled ? onFulfilled(this.value) : this.value;
          resolve(x);
        } catch (e) {
          reject(e);
        }
      });
    const handleRejected = () =>
      queueMicrotask(() => {
        try {
          const x = onRejected ? onRejected(this.reason) : this.reason;
          resolve(x); // 这里简化为透传,生产实现需区分 resolvePromise
        } catch (e) {
          reject(e);
        }
      });

    if (this.state === FULFILLED) handleFulfilled();
    else if (this.state === REJECTED) handleRejected();
    else {
      this.onFulfilledCallbacks.push(handleFulfilled);
      this.onRejectedCallbacks.push(handleRejected);
    }
  });
};