面试题库 词条目录
前端Wiki/词条/手写 Promise

手写 Promise

定义手写实现 Promise 的核心 API,考察对异步状态机与微任务的理解

手写 Promise 先搭状态机:三个状态 pending、fulfilled、rejected 只能单向流转;then 方法返回新 Promise 实现链式调用,回调要用 try/catch 包裹以免吞掉异常;then 的参数不是函数时值要继续向下传递,这就是值穿透。resolve 与 reject 的值一旦确定不可变。

进阶手写常考 Promise.all、race、allSettled 与重试包装器。all 的要点是计数器加结果数组按索引填充,全部成功才 resolve,一个失败立即 race 出去;race 的第一个结果决定最终状态。面试时强调 then 的回调必须放进微任务队列(用 queueMicrotask 或已有的 Promise 模拟)。

JavaScript
// 简版 Promise:状态机 + then 链式调用
class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = undefined;
    this.cbs = [];
    const resolve = v => {
      if (this.state !== 'pending') return;
      this.state = 'fulfilled'; this.value = v;
      this.cbs.forEach(cb => cb.onFul(v));
    };
    const reject = r => {
      if (this.state !== 'pending') return;
      this.state = 'rejected'; this.value = r;
      this.cbs.forEach(cb => cb.onRej(r));
    };
    try { executor(resolve, reject); } catch (e) { reject(e); }
  }
  then(onFul, onRej) {
    return new MyPromise((res, rej) => {
      const ful = v => { try { res(onFul ? onFul(v) : v); } catch (e) { rej(e); } };
      const rej = r => { try { res(onRej ? onRej(r) : r); } catch (e) { rej(e); } };
      if (this.state === 'fulfilled') ful(this.value);
      else if (this.state === 'rejected') rej(this.value);
      else this.cbs.push({ onFul: ful, onRej: rej });
    });
  }
}

new MyPromise(res => setTimeout(() => res(1), 100))
  .then(v => { console.log('第一个', v); return v + 1; })
  .then(v => console.log('第二个', v));   // 1 -> 2
⚠ 常见误区
🔗 相关词条Promise 与异步编程事件循环与宏任务微任务
← 返回来源章节Promise 与异步编程