面试手写 Promise:链式 + 静态方法全实现

ES5 语法 实现一个 符合 Promise/A+ 规范 的完整 Promise,附 Promise.all/race/finally 等静态方法,面试手写无压力。


一、手写核心 Promise(符合 A+)

1. 结构

js 复制代码
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

function MyPromise(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(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 (err) {
    reject(err);
  }
}

2. then 方法(链式核心)

js 复制代码
MyPromise.prototype.then = function (onFulfilled, onRejected) {
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
  onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };

  return new MyPromise((resolve, reject) => {
    const handle = () => {
      try {
        const result = this.state === FULFILLED
          ? onFulfilled(this.value)
          : onRejected(this.reason);
        resolvePromise(result, resolve, reject);
      } catch (err) {
        reject(err);
      }
    };

    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(handle);
      this.onRejectedCallbacks.push(handle);
    } else {
      setTimeout(handle, 0);
    }
  });
};

function resolvePromise(result, resolve, reject) {
  if (result instanceof MyPromise) {
    result.then(resolve, reject);
  } else {
    resolve(result);
  }
}

二、静态方法全家桶

1. Promise.resolve / reject

js 复制代码
MyPromise.resolve = value => new MyPromise(resolve => resolve(value));
MyPromise.reject = reason => new MyPromise((_, reject) => reject(reason));

2. Promise.all(并发等待)

js 复制代码
MyPromise.all = function (promises) {
  return new MyPromise((resolve, reject) => {
    let count = 0;
    const results = [];
    promises.forEach((p, i) => {
      MyPromise.resolve(p).then(
        val => {
          results[i] = val;
          if (++count === promises.length) resolve(results);
        },
        reject
      );
    });
  });
};

3. Promise.race(谁先完成用谁)

js 复制代码
MyPromise.race = function (promises) {
  return new MyPromise((resolve, reject) => {
    promises.forEach(p => MyPromise.resolve(p).then(resolve, reject));
  });
};

4. Promise.finally(无论成功失败都执行)

js 复制代码
MyPromise.prototype.finally = function (callback) {
  return this.then(
    val => MyPromise.resolve(callback()).then(() => val),
    err => MyPromise.resolve(callback()).then(() => { throw err; })
  );
};

三、完整测试用例

js 复制代码
// 1. 基本链式
new MyPromise(resolve => resolve(1))
  .then(val => val + 1)
  .then(val => console.log(val)); // 2

// 2. 并发
MyPromise.all([
  new MyPromise(resolve => setTimeout(() => resolve('a'), 100)),
  new MyPromise(resolve => setTimeout(() => resolve('b'), 200))
]).then(console.log); // ['a', 'b']
相关推荐
meilindehuzi_a5 小时前
从零理解并实现 RAG:用 LangChain.js 构建语义检索问答系统
开发语言·javascript·langchain
世界哪有真情6 小时前
拿人类意识卡 AI?等于用 bug 验收正式产品
前端·人工智能·后端
鱼樱前端7 小时前
别再自己拼凑了!这款 Vue 3.5+ 严肃产品级组件库,把 AI 对话、工作流和复杂数据全包了!
javascript·vue.js·github
Listen·Rain7 小时前
Vue3:setup详解
前端·javascript·vue.js
Patrick_Wilson8 小时前
修好 bug 只是开始:一次由监控需求反向重构日志结构的复盘
前端·监控·数据可视化
kyriewen8 小时前
面试官让我优化一个卡死的表格,我打开 Claude 五秒重写,他放下咖啡问我要不要来当组长
前端·javascript·面试
小粉粉hhh9 小时前
React(二)——dom、组件间通信、useEffect
前端·javascript·react.js
Csvn9 小时前
🤖 AI 生成前端代码的 5 个典型翻车现场及修复指南
前端
IT_陈寒10 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
黄敬峰11 小时前
从零搭建 RAG 应用 —— 一个故事带你彻底搞懂检索增强生成
面试