Promise:三态、链式调用与 thenable 采纳

先理解原理和示例,再练习完整口述与追问。

执行器同步、状态只确定一次、回调异步、返回值透传、错误传播、链式循环。

Promise 是一次结算的状态机,then 返回新的 Promise,回调返回值或异常决定后续状态;返回 thenable 还需要安全采纳并防止多次调用和循环引用。回调必须按异步规则执行,不能因为已经 fulfilled 就同步运行。

先测 executor 同步日志与 then 异步日志,再测链式返回普通值、返回 Promise、抛异常、缺失处理器透传和自引用。thenable 若先 resolve 后 reject,只能采纳第一次;读取 then 的 getter 也可能抛错。对每条链画状态与值的流转。

简化实现没有自动拥有原生全部迭代器组合器、取消或调度优化。严格符合规范需要更系统的兼容测试,面试应准确说明范围。

Promise 保存 pending/fulfilled/rejected 状态,then 必须返回新 Promise;回调正常返回就解析新 Promise,抛错就拒绝。resolve 不能只把 thenable 当普通对象,要采用它的最终结果,同时防止重复回调和链式自解析。下面教学版本提供 then/catch、resolve/reject 与基本 thenable 解析,使用 queueMicrotask 调度;不实现完整原生 Promise、子类 species、finally 或宿主未处理拒绝追踪。

js
class MiniPromise {
  constructor(executor) {
    if (typeof executor !== 'function') throw new TypeError('executor 必须是函数')
    this.state = 'pending'
    this.value = undefined
    this.reactions = []
    let locked = false
    const resolve = value => {
      if (locked) return
      locked = true
      this._adopt(value)
    }
    const reject = reason => {
      if (locked) return
      locked = true
      this._settle('rejected', reason)
    }
    try { executor(resolve, reject) }
    catch (error) { reject(error) }
  }

  _settle(state, value) {
    if (this.state !== 'pending') return
    this.state = state
    this.value = value
    const reactions = this.reactions
    this.reactions = []
    for (const reaction of reactions) queueMicrotask(reaction)
  }

  _adopt(value) {
    if (value === this) {
      this._settle('rejected', new TypeError('不能解析为自身'))
      return
    }
    const objectLike = value !== null &&
      (typeof value === 'object' || typeof value === 'function')
    if (objectLike) {
      let then
      try { then = value.then }
      catch (error) { this._settle('rejected', error); return }
      if (typeof then === 'function') {
        queueMicrotask(() => {
          let called = false
          try {
            Reflect.apply(then, value, [next => {
              if (called) return
              called = true
              this._adopt(next)
            }, reason => {
              if (called) return
              called = true
              this._settle('rejected', reason)
            }])
          } catch (error) {
            if (!called) {
              called = true
              this._settle('rejected', error)
            }
          }
        })
        return
      }
    }
    this._settle('fulfilled', value)
  }

  then(onFulfilled, onRejected) {
    return new MiniPromise((resolve, reject) => {
      const reaction = () => {
        const fulfilled = this.state === 'fulfilled'
        const handler = fulfilled ? onFulfilled : onRejected
        if (typeof handler !== 'function') {
          if (fulfilled) resolve(this.value)
          else reject(this.value)
          return
        }
        try { resolve(handler(this.value)) }
        catch (error) { reject(error) }
      }
      if (this.state === 'pending') this.reactions.push(reaction)
      else queueMicrotask(reaction)
    })
  }

  catch(onRejected) { return this.then(undefined, onRejected) }
  static resolve(value) {
    return value instanceof MiniPromise ? value : new MiniPromise(resolve => resolve(value))
  }
  static reject(reason) { return new MiniPromise((resolve, reject) => reject(reason)) }
}

示例:MiniPromise.resolve(1).then(x=>x+1) 兑现为 2;回调 throw 后可由 catch 接住;then 返回自身形成的直接链式循环会拒绝。执行器先 resolve 一个未完成 Promise,再 reject,也以第一次 resolve 采用的结果为准。恶意 thenable 自己无限产生循环不是本实现承诺解决的情况,不把有限用例通过说成完整规范认证。空间与注册回调及链长有关。Promises/A+:then 与解析过程的定义

返回:前端总清单。