【手写 Promise A+规范实现 - 从零开始构建异步编程基石】

发布于:2025-07-13 ⋅ 阅读:(9) ⋅ 点赞:(0)

手写 Promise A+规范实现 - 从零开始构建异步编程基石

引言

Promise 是现代 JavaScript 异步编程的核心,而 Promise/A+规范则是 Promise 实现的标准。本文将从最基础的概念开始,逐步实现一个完整的 Promise A+规范,帮助深入理解 Promise 的工作原理。

什么是 Promise A+规范?

📋 规范定义

Promise A+规范(Promise/A+ Specification)是一个开放标准,定义了 Promise 对象的行为规范。它是对早期 Promise/A 规范的改进和完善,目前是 JavaScript Promise 实现的事实标准。

🎯 规范的作用

  1. 统一标准:为不同的 Promise 实现提供统一的行为标准
  2. 互操作性:确保不同库的 Promise 可以相互兼容
  3. 可预测性:开发者可以依赖一致的 Promise 行为
  4. 测试基准:提供标准化的测试套件验证实现的正确性

🏛️ 历史背景

2009年 - CommonJS 提出 Promise/A 规范
2012年 - Promise/A+ 规范发布,修复了 A 规范的问题
2015年 - ES6 正式将 Promise 纳入标准,基于 A+ 规范
2017年 - async/await 语法糖,基于 Promise 实现

📊 规范的核心要求

Promise A+规范主要定义了以下几个方面:

1. 术语定义
  • promise:一个有 then 方法的对象或函数
  • thenable:定义了 then 方法的对象或函数
  • value:任何合法的 JavaScript 值
  • exception:使用 throw 语句抛出的值
  • reason:表示 promise 被拒绝原因的值
2. 状态要求
// Promise 必须处于以下三种状态之一:
const PENDING = 'pending'; // 等待态
const FULFILLED = 'fulfilled'; // 执行态
const REJECTED = 'rejected'; // 拒绝态

// 状态转换规则:
// pending -> fulfilled (不可逆)
// pending -> rejected (不可逆)
// fulfilled 和 rejected 状态不能再改变
3. then 方法规范
// then 方法签名
promise.then(onFulfilled, onRejected);

// 核心要求:
// - then 方法必须返回一个 promise
// - onFulfilled 和 onRejected 都是可选参数
// - 如果不是函数,必须被忽略
// - 必须异步执行
// - 同一个 promise 的 then 方法可以被调用多次
4. Promise 解析过程

规范详细定义了如何处理 then 方法返回的各种值:

  • 普通值:直接 resolve
  • Promise 对象:等待其状态确定
  • thenable 对象:尝试调用其 then 方法
  • 异常处理:捕获并 reject

🔍 规范的重要性

为什么需要标准化?
// 没有标准化之前,不同库的 Promise 行为可能不一致
// 库A的实现
libraryA.createPromise().then(callback); // 同步执行回调

// 库B的实现
libraryB.createPromise().then(callback); // 异步执行回调

// 这种不一致性会导致代码行为不可预测
Promise A+规范解决的问题
  1. 执行时机统一:所有 then 回调必须异步执行
  2. 错误处理标准化:统一的异常捕获和传播机制
  3. 链式调用规范:明确定义 then 方法的返回值处理
  4. 互操作性保证:不同实现的 Promise 可以互相调用

📚 规范文档结构

Promise A+规范文档包含以下主要部分:

  1. 术语:定义关键概念
  2. 要求:详细的行为规范
  3. 注释:实现指导和澄清
  4. 测试套件:验证实现正确性的测试用例

🧪 规范测试

Promise A+规范提供了官方测试套件:

# 安装测试套件
npm install promises-aplus-tests

# 运行测试
npx promises-aplus-tests <your-promise-implementation>

测试套件包含 872 个测试用例,覆盖了规范的所有要求。

🌟 现实意义

对开发者的价值
  1. 学习异步编程:理解异步操作的本质
  2. 提升代码质量:写出更可靠的异步代码
  3. 框架理解:深入理解现代前端框架的异步机制
  4. 面试准备:高级前端面试的重要考点
对生态系统的影响
  1. 库的兼容性:确保不同 Promise 库可以互操作
  2. 标准化进程:推动 JavaScript 语言标准的发展
  3. 工具链支持:为构建工具和测试框架提供基础

💡 学习路径建议

了解 Promise 基本概念
学习 Promise A+ 规范
手写简单 Promise 实现
逐步完善功能
通过官方测试套件
理解实际应用场景
掌握高级异步模式

通过理解 Promise A+规范,我们不仅能够实现一个标准的 Promise,更重要的是能够深入理解异步编程的本质,为编写高质量的 JavaScript 代码奠定坚实基础。


第一章:理解 Promise 的基本概念

1.1 什么是 Promise

Promise 是一个代表异步操作最终完成或失败的对象。它有三种状态:

  • Pending(等待中):初始状态,既不是成功,也不是失败
  • Fulfilled(已成功):操作成功完成
  • Rejected(已失败):操作失败
// Promise的基本使用
const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    resolve('成功的结果');
    // 或者 reject('失败的原因');
  }, 1000);
});

promise.then(
  (result) => console.log('成功:', result),
  (error) => console.log('失败:', error)
);

1.2 Promise 的核心特性

  1. 状态不可逆:一旦从 pending 变为 fulfilled 或 rejected,状态就不能再改变
  2. 值不可变:Promise 的值一旦确定就不能再改变
  3. 异步执行:then 回调总是异步执行的

1.3 Promise 执行流程可视化解析

让我们通过一个完整的流程图来理解 Promise 的工作机制:

🔄 完整执行流程
📦 创建 Promise
    ↓
🚀 立即执行构造函数 (executor)
    ↓
⏳ 等待 resolve/reject 调用时机
    ↓
📞 调用 promise.then()
    ↓
🤔 判断当前状态
    ├─ ✅ 已完成 → 直接执行回调
    └─ ⏳ 等待中 → 收集回调到数组
    ↓
⚡ resolve/reject 被调用
    ↓
🔄 改变状态 + 触发所有等待的回调
📋 详细步骤分析

步骤 1:创建 Promise

const promise = new Promise((resolve, reject) => {
  // 这里的代码立即执行!
  console.log('构造函数执行');

  // 设置异步操作
  setTimeout(() => {
    resolve('成功结果'); // 这是改变状态的契机
  }, 1000);
});

步骤 2:调用 then 方法

promise.then((value) => {
  console.log('收到结果:', value);
});

步骤 3:状态判断与处理

// then 方法内部逻辑
then(onFulfilled) {
  if (this.state === FULFILLED) {
    // 情况A:已经完成,直接执行
    onFulfilled(this.value);
  } else if (this.state === PENDING) {
    // 情况B:还在等待,收集回调
    this.onFulfilledCallbacks.push(() => {
      onFulfilled(this.value);
    });
  }
}

步骤 4:resolve 触发机制

const resolve = (value) => {
  if (this.state === PENDING) {
    // 🔄 改变状态
    this.state = FULFILLED;
    this.value = value;

    // ⚡ 触发所有等待的回调
    this.onFulfilledCallbacks.forEach((callback) => {
      callback(); // 执行之前收集的回调
    });
  }
};
🎯 关键时机理解
  1. 构造函数执行时机:立即同步执行
  2. resolve/reject 调用时机:由异步操作决定(如 setTimeout、网络请求等)
  3. then 回调执行时机
    • 状态已确定 → 立即执行
    • 状态未确定 → 等待状态改变后执行
🔍 实际执行示例
console.log('1. 开始');

const promise = new Promise((resolve) => {
  console.log('2. 构造函数执行');
  setTimeout(() => {
    console.log('4. resolve 被调用');
    resolve('成功');
  }, 1000);
});

console.log('3. Promise 创建完成');

promise.then((value) => {
  console.log('5. then 回调执行:', value);
});

// 输出顺序:
// 1. 开始
// 2. 构造函数执行
// 3. Promise 创建完成
// 4. resolve 被调用 (1秒后)
// 5. then 回调执行: 成功
💡 核心理解要点
  1. 状态改变的契机:只有调用 resolve/reject 才能改变 Promise 状态
  2. 回调收集机制:then/catch 方法负责判断状态和收集回调
  3. 触发时机:resolve 调用时会触发所有等待的回调函数
  4. 自动化处理:整个过程通过状态管理和回调数组实现自动化
then 方法的执行逻辑
promise.then(onFulfilled, onRejected);

执行分析

  1. then 方法本身立即执行:注册回调函数或直接执行回调
  2. 回调函数的执行时机
    • 如果 Promise 已经 fulfilled/rejected:异步执行回调
    • 如果 Promise 还是 pending:将回调保存到数组中,等待状态改变
常见误解澄清

误解new Promise(resolve => { console.log(1) }) 相当于 resolve => { console.log(1) }

正确理解

// 这个函数会立即执行
new Promise((resolve) => {
  console.log(1); // 立即输出 1
  // resolve 是一个函数,可以在任何时候调用来改变状态
});

// 而不是简单的函数赋值
const fn = (resolve) => {
  console.log(1); // 只有调用 fn 时才会执行
};

第二章:最简单的 Promise 实现

让我们从最基础的版本开始:

// 定义Promise的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
  constructor(executor) {
    // 初始状态
    this.state = PENDING;
    this.value = undefined;
    this.reason = undefined;

    // resolve函数
    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = FULFILLED;
        this.value = value;
      }
    };

    // reject函数
    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
      }
    };

    // 执行executor
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  // 简单的then方法
  then(onFulfilled, onRejected) {
    if (this.state === FULFILLED) {
      onFulfilled(this.value);
    }

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

测试基础版本

// 测试同步resolve
const promise1 = new MyPromise((resolve, reject) => {
  resolve('同步成功');
});

promise1.then(
  (value) => console.log('成功:', value),
  (reason) => console.log('失败:', reason)
);
// 输出: 成功: 同步成功

问题:这个版本只能处理同步操作,无法处理异步操作。

第三章:支持异步操作

异步操作的关键是在 Promise 状态还是 pending 时,需要将回调函数保存起来,等状态改变时再执行。

class MyPromise {
  constructor(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((callback) => callback());
      }
    };

    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
        // 执行所有失败回调
        this.onRejectedCallbacks.forEach((callback) => callback());
      }
    };

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

  then(onFulfilled, onRejected) {
    if (this.state === FULFILLED) {
      onFulfilled(this.value);
    }

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

    // 处理pending状态
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        onFulfilled(this.value);
      });

      this.onRejectedCallbacks.push(() => {
        onRejected(this.reason);
      });
    }
  }
}

测试异步版本

// 测试异步resolve
const promise2 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('异步成功');
  }, 1000);
});

promise2.then(
  (value) => console.log('成功:', value),
  (reason) => console.log('失败:', reason)
);
// 1秒后输出: 成功: 异步成功

第四章:实现链式调用

Promise 的核心特性之一是链式调用,每个 then 方法都应该返回一个新的 Promise。

class MyPromise {
  constructor(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((callback) => callback());
      }
    };

    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((callback) => callback());
      }
    };

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

  then(onFulfilled, onRejected) {
    // 返回新的Promise实现链式调用
    return new MyPromise((resolve, reject) => {
      // 处理fulfilled状态
      if (this.state === FULFILLED) {
        try {
          const result = onFulfilled(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      }

      // 处理rejected状态
      if (this.state === REJECTED) {
        try {
          const result = onRejected(this.reason);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      }

      // 处理pending状态
      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          try {
            const result = onFulfilled(this.value);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });

        this.onRejectedCallbacks.push(() => {
          try {
            const result = onRejected(this.reason);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });
      }
    });
  }
}

测试链式调用

const promise3 = new MyPromise((resolve, reject) => {
  resolve(1);
});

promise3
  .then((value) => {
    console.log('第一步:', value); // 1
    return value + 1;
  })
  .then((value) => {
    console.log('第二步:', value); // 2
    return value * 2;
  })
  .then((value) => {
    console.log('第三步:', value); // 4
  });

第五章:处理 Promise 值的解析

根据 Promise A+规范,then 方法的回调函数可能返回:

  1. 普通值
  2. Promise 对象
  3. thenable 对象

我们需要一个专门的函数来处理这些情况:

5.1 为什么需要 resolvePromise 函数?

在 Promise 链式调用中,每个 then 方法都会返回一个新的 Promise。但是 then 的回调函数可能返回各种不同类型的值,我们需要统一处理这些情况:

// 情况1:返回普通值
promise.then(() => {
  return 'hello'; // 普通字符串
});

// 情况2:返回Promise对象
promise.then(() => {
  return new Promise((resolve) => resolve('world')); // Promise实例
});

// 情况3:返回thenable对象
promise.then(() => {
  return {
    then: function (resolve) {
      resolve('thenable');
    }
  }; // 有then方法的对象
});

// 情况4:抛出异常
promise.then(() => {
  throw new Error('出错了'); // 异常
});

5.2 变量 x 的含义

在 Promise A+规范中,x 是一个约定俗成的变量名,代表 then 回调函数的返回值。规范文档中就是用 x 来表示这个值:

// Promise A+规范原文中的描述:
// Let x be the result of calling onFulfilled or onRejected
// 让 x 成为调用 onFulfilled 或 onRejected 的结果

// 在我们的实现中:
then(onFulfilled, onRejected) {
  return new MyPromise((resolve, reject) => {
    if (this.state === FULFILLED) {
      try {
        const x = onFulfilled(this.value); // x 就是回调函数的返回值
        resolvePromise(promise2, x, resolve, reject); // 处理这个返回值
      } catch (error) {
        reject(error);
      }
    }
  });
}

5.3 resolvePromise 函数详解

让我们逐步分析这个函数的实现:

🔍 函数签名解析
function resolvePromise(promise2, x, resolve, reject) {
  // promise2: 当前then方法返回的新Promise
  // x: then回调函数的返回值(需要解析的值)
  // resolve: promise2的resolve函数
  // reject: promise2的reject函数
}
📋 处理步骤详解
// Promise解析函数 - 带详细注释版本
function resolvePromise(promise2, x, resolve, reject) {
  // 步骤1:检查循环引用
  // 如果then回调返回了promise2自身,会造成无限循环
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise'));
  }

  // 步骤2:防止重复调用标志
  // 因为thenable对象的then方法可能同时调用resolve和reject
  let called = false;

  // 步骤3:处理Promise实例
  if (x instanceof MyPromise) {
    if (x.state === PENDING) {
      // 如果x还在等待,等它完成后再处理结果
      x.then((value) => {
        resolvePromise(promise2, value, resolve, reject); // 递归处理
      }, reject);
    } else {
      // 如果x已经完成,直接使用其结果
      x.then(resolve, reject);
    }
    return;
  }

  // 步骤4:处理thenable对象(有then方法的对象或函数)
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    try {
      // 获取then属性(可能会抛出异常)
      const then = x.then;

      // 如果then是函数,说明是thenable对象
      if (typeof then === 'function') {
        // 调用then方法,传入成功和失败回调
        then.call(
          x, // this指向x
          (value) => {
            // 成功回调
            if (called) return; // 防止重复调用
            called = true;
            resolvePromise(promise2, value, resolve, reject); // 递归处理返回值
          },
          (reason) => {
            // 失败回调
            if (called) return; // 防止重复调用
            called = true;
            reject(reason);
          }
        );
      } else {
        // then不是函数,x就是普通对象,直接resolve
        resolve(x);
      }
    } catch (error) {
      // 获取then属性或调用then方法时出错
      if (called) return; // 防止重复调用
      called = true;
      reject(error);
    }
  } else {
    // 步骤5:x是普通值(字符串、数字、布尔值等)
    resolve(x);
  }
}

5.4 实际执行示例

让我们通过具体例子来理解每种情况:

示例 1:返回普通值
const promise1 = new MyPromise((resolve) => resolve(1));

const promise2 = promise1.then((value) => {
  return value + 1; // 返回普通值 2
});

// resolvePromise 执行过程:
// 1. x = 2 (普通数字)
// 2. 不是Promise实例,不是对象/函数
// 3. 直接 resolve(2)
// 4. promise2 变为 fulfilled 状态,值为 2
示例 2:返回 Promise 对象
const promise1 = new MyPromise((resolve) => resolve(1));

const promise2 = promise1.then((value) => {
  return new MyPromise((resolve) => {
    setTimeout(() => resolve(value * 2), 1000);
  }); // 返回Promise实例
});

// resolvePromise 执行过程:
// 1. x = 新的MyPromise实例
// 2. x instanceof MyPromise 为 true
// 3. x.state === PENDING,等待x完成
// 4. 1秒后x resolve(2),触发 resolvePromise(promise2, 2, resolve, reject)
// 5. 第二次调用时,x = 2,直接 resolve(2)
// 6. promise2 变为 fulfilled 状态,值为 2
示例 3:返回 thenable 对象
const promise1 = new MyPromise((resolve) => resolve(1));

const promise2 = promise1.then((value) => {
  return {
    then: function (onFulfilled, onRejected) {
      setTimeout(() => onFulfilled(value * 3), 500);
    }
  }; // 返回thenable对象
});

// resolvePromise 执行过程:
// 1. x = thenable对象
// 2. typeof x === 'object' 为 true
// 3. then = x.then,typeof then === 'function' 为 true
// 4. 调用 then.call(x, successCallback, errorCallback)
// 5. 500ms后thenable调用 onFulfilled(3)
// 6. 触发 resolvePromise(promise2, 3, resolve, reject)
// 7. 第二次调用时,x = 3,直接 resolve(3)
// 8. promise2 变为 fulfilled 状态,值为 3
示例 4:循环引用检测
const promise1 = new MyPromise((resolve) => resolve(1));

const promise2 = promise1.then((value) => {
  return promise2; // 返回promise2自身!
});

// resolvePromise 执行过程:
// 1. x = promise2
// 2. promise2 === x 为 true
// 3. 立即 reject(new TypeError('Chaining cycle detected for promise'))
// 4. promise2 变为 rejected 状态

5.5 为什么需要 called 标志?

// 恶意的thenable对象可能同时调用resolve和reject
const maliciousThenable = {
  then: function (resolve, reject) {
    resolve('success');
    reject('error'); // 恶意调用
    resolve('success again'); // 再次恶意调用
  }
};

// 没有called标志的话,promise2的状态可能被多次改变
// 有了called标志,只有第一次调用生效

5.6 递归调用的必要性

// 嵌套的thenable对象
const nestedThenable = {
  then: function (resolve) {
    resolve({
      then: function (resolve2) {
        resolve2('最终值');
      }
    });
  }
};

// 需要递归调用resolvePromise来逐层解析:
// 第一次:x = nestedThenable,调用其then方法
// 第二次:x = 内层thenable,再次调用其then方法
// 第三次:x = '最终值',直接resolve

5.7 完整的 resolvePromise 实现

// Promise解析函数
function resolvePromise(promise2, x, resolve, reject) {
  // 避免循环引用
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise'));
  }

  // 避免重复调用
  let called = false;

  // 如果x是Promise实例
  if (x instanceof MyPromise) {
    if (x.state === PENDING) {
      x.then((value) => {
        resolvePromise(promise2, value, resolve, reject);
      }, reject);
    } else {
      x.then(resolve, reject);
    }
    return;
  }

  // 如果x是对象或函数
  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    try {
      const then = x.then;

      // 如果then是函数,说明是thenable对象
      if (typeof then === 'function') {
        then.call(
          x,
          (value) => {
            if (called) return;
            called = true;
            resolvePromise(promise2, value, resolve, reject);
          },
          (reason) => {
            if (called) return;
            called = true;
            reject(reason);
          }
        );
      } else {
        // then不是函数,直接resolve
        resolve(x);
      }
    } catch (error) {
      if (called) return;
      called = true;
      reject(error);
    }
  } else {
    // x是普通值
    resolve(x);
  }
}

总结resolvePromise 函数是 Promise A+规范的核心实现,它负责正确处理 then 回调函数返回的各种类型的值。变量 x 代表这个返回值,函数通过类型检查和递归调用,确保 Promise 链能够正确传递和转换值。

class MyPromise { constructor(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((callback) => callback());
  }
};

const reject = (reason) => {
  if (this.state === PENDING) {
    this.state = REJECTED;
    this.reason = reason;
    this.onRejectedCallbacks.forEach((callback) => callback());
  }
};

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

}

then(onFulfilled, onRejected) { // 参数可选,提供默认值 onFulfilled = typeof onFulfilled === ‘function’ ? onFulfilled : (value) => value; onRejected = typeof onRejected === ‘function’ ? onRejected : (reason) => { throw reason; };

const promise2 = new MyPromise((resolve, reject) => {
  if (this.state === FULFILLED) {
    // 异步执行
    setTimeout(() => {
      try {
        const x = onFulfilled(this.value);
        resolvePromise(promise2, x, resolve, reject);
      } catch (error) {
        reject(error);
      }
    }, 0);
  }

  if (this.state === REJECTED) {
    setTimeout(() => {
      try {
        const x = onRejected(this.reason);
        resolvePromise(promise2, x, resolve, reject);
      } catch (error) {
        reject(error);
      }
    }, 0);
  }

  if (this.state === PENDING) {
    this.onFulfilledCallbacks.push(() => {
      setTimeout(() => {
        try {
          const x = onFulfilled(this.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0);
    });

    this.onRejectedCallbacks.push(() => {
      setTimeout(() => {
        try {
          const x = onRejected(this.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0);
    });
  }
});

return promise2;

} }


## 第六章:添加静态方法

### 6.1 Promise.resolve

```javascript
MyPromise.resolve = function (value) {
  return new MyPromise((resolve, reject) => {
    resolve(value);
  });
};

6.2 Promise.reject

MyPromise.reject = function (reason) {
  return new MyPromise((resolve, reject) => {
    reject(reason);
  });
};

6.3 Promise.all

MyPromise.all = function (promises) {
  return new MyPromise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return reject(new TypeError('参数必须是数组'));
    }

    const results = [];
    let completedCount = 0;

    if (promises.length === 0) {
      return resolve(results);
    }

    promises.forEach((promise, index) => {
      MyPromise.resolve(promise).then(
        (value) => {
          results[index] = value;
          completedCount++;

          if (completedCount === promises.length) {
            resolve(results);
          }
        },
        (reason) => {
          reject(reason);
        }
      );
    });
  });
};

6.4 Promise.race

MyPromise.race = function (promises) {
  return new MyPromise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return reject(new TypeError('参数必须是数组'));
    }

    promises.forEach((promise) => {
      MyPromise.resolve(promise).then(resolve, reject);
    });
  });
};

第七章:添加实例方法

7.1 catch 方法

MyPromise.prototype.catch = function (onRejected) {
  return this.then(null, onRejected);
};

7.2 finally 方法

MyPromise.prototype.finally = function (onFinally) {
  return this.then(
    (value) => MyPromise.resolve(onFinally()).then(() => value),
    (reason) =>
      MyPromise.resolve(onFinally()).then(() => {
        throw reason;
      })
  );
};

第八章:完整的 Promise A+实现

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

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise'));
  }

  let called = false;

  if (x instanceof MyPromise) {
    if (x.state === PENDING) {
      x.then((value) => {
        resolvePromise(promise2, value, resolve, reject);
      }, reject);
    } else {
      x.then(resolve, reject);
    }
    return;
  }

  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    try {
      const then = x.then;

      if (typeof then === 'function') {
        then.call(
          x,
          (value) => {
            if (called) return;
            called = true;
            resolvePromise(promise2, value, resolve, reject);
          },
          (reason) => {
            if (called) return;
            called = true;
            reject(reason);
          }
        );
      } else {
        resolve(x);
      }
    } catch (error) {
      if (called) return;
      called = true;
      reject(error);
    }
  } else {
    resolve(x);
  }
}

class MyPromise {
  constructor(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((callback) => callback());
      }
    };

    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((callback) => callback());
      }
    };

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

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === 'function'
        ? onRejected
        : (reason) => {
            throw reason;
          };

    const promise2 = new MyPromise((resolve, reject) => {
      if (this.state === FULFILLED) {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }

      if (this.state === REJECTED) {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }

      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });

        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
      }
    });

    return promise2;
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(onFinally) {
    return this.then(
      (value) => MyPromise.resolve(onFinally()).then(() => value),
      (reason) =>
        MyPromise.resolve(onFinally()).then(() => {
          throw reason;
        })
    );
  }

  static resolve(value) {
    return new MyPromise((resolve, reject) => {
      resolve(value);
    });
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason);
    });
  }

  static all(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new TypeError('参数必须是数组'));
      }

      const results = [];
      let completedCount = 0;

      if (promises.length === 0) {
        return resolve(results);
      }

      promises.forEach((promise, index) => {
        MyPromise.resolve(promise).then(
          (value) => {
            results[index] = value;
            completedCount++;

            if (completedCount === promises.length) {
              resolve(results);
            }
          },
          (reason) => {
            reject(reason);
          }
        );
      });
    });
  }

  static race(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new TypeError('参数必须是数组'));
      }

      promises.forEach((promise) => {
        MyPromise.resolve(promise).then(resolve, reject);
      });
    });
  }
}

第九章:测试和验证

9.1 基础功能测试

// 测试基本功能
console.log('=== 基础功能测试 ===');

const promise1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('异步成功');
  }, 1000);
});

promise1
  .then((value) => {
    console.log('结果:', value);
    return value + ' -> 链式调用';
  })
  .then((value) => {
    console.log('链式结果:', value);
  });

// 测试错误处理
const promise2 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject('异步失败');
  }, 500);
});

promise2.catch((error) => {
  console.log('捕获错误:', error);
});

9.2 静态方法测试

// 测试Promise.all
console.log('=== Promise.all测试 ===');

const p1 = MyPromise.resolve(1);
const p2 = MyPromise.resolve(2);
const p3 = MyPromise.resolve(3);

MyPromise.all([p1, p2, p3]).then((results) => {
  console.log('Promise.all结果:', results); // [1, 2, 3]
});

// 测试Promise.race
console.log('=== Promise.race测试 ===');

const fast = new MyPromise((resolve) => setTimeout(() => resolve('快'), 100));
const slow = new MyPromise((resolve) => setTimeout(() => resolve('慢'), 200));

MyPromise.race([fast, slow]).then((result) => {
  console.log('Promise.race结果:', result); // '快'
});

9.3 Promise A+规范测试

// 用于Promise A+规范测试的适配器
MyPromise.deferred = function () {
  const dfd = {};
  dfd.promise = new MyPromise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};

// 可以使用promises-aplus-tests库进行完整测试
// npm install promises-aplus-tests
// npx promises-aplus-tests MyPromise.js

第十章:性能优化和最佳实践

10.1 微任务优化

在真实的 Promise 实现中,回调函数应该在微任务队列中执行,而不是宏任务队列:

// 使用queueMicrotask或MutationObserver实现微任务
function nextTick(callback) {
  if (typeof queueMicrotask === 'function') {
    queueMicrotask(callback);
  } else if (typeof MutationObserver === 'function') {
    const observer = new MutationObserver(callback);
    const textNode = document.createTextNode('1');
    observer.observe(textNode, { characterData: true });
    textNode.data = '2';
  } else {
    setTimeout(callback, 0);
  }
}

// 在Promise实现中替换setTimeout
// setTimeout(() => { ... }, 0);
// 改为
// nextTick(() => { ... });

10.2 内存优化

// 避免内存泄漏的优化版本
class OptimizedPromise extends MyPromise {
  then(onFulfilled, onRejected) {
    // 在状态确定后清理回调数组
    const promise2 = super.then(onFulfilled, onRejected);

    // 如果当前Promise已经settled,清理回调数组
    if (this.state !== PENDING) {
      this.onFulfilledCallbacks = [];
      this.onRejectedCallbacks = [];
    }

    return promise2;
  }
}

第十一章:常见疑问解答

11.1 Promise 错误处理机制深度解析

常见疑问:为什么在 rejected 状态下,onRejected 处理后会 resolve?catch 的原理是什么?

// 处理rejected状态
if (this.state === REJECTED) {
  try {
    const result = onRejected(this.reason);
    resolve(result); // 为什么这里是resolve而不是reject?
  } catch (error) {
    reject(error);
  }
}
🔍 错误处理的核心原理

关键理解:Promise 链中的错误处理遵循"错误恢复"机制,即:

  • 如果错误被成功处理(onRejected 正常执行),Promise 链会恢复到 fulfilled 状态
  • 只有当处理错误的过程中又出现新错误时,才会继续保持 rejected 状态
📋 详细执行流程
// 示例1:错误被成功处理
Promise.reject('原始错误')
  .then(
    null, // onFulfilled
    (error) => {
      console.log('处理错误:', error); // 输出: 处理错误: 原始错误
      return '错误已修复'; // 返回正常值
    }
  )
  .then((value) => {
    console.log('恢复正常:', value); // 输出: 恢复正常: 错误已修复
  });

执行分析

  1. Promise.reject('原始错误') 创建一个 rejected 状态的 Promise
  2. 第一个 thenonRejected 处理了错误,返回了正常值
  3. 由于 onRejected 正常执行(没有抛出异常),新的 Promise 变为 fulfilled 状态
  4. 第二个 thenonFulfilled 接收到恢复后的值
🔄 错误传播与恢复机制
// 完整的错误处理示例
Promise.resolve('开始')
  .then((value) => {
    console.log('步骤1:', value);
    throw new Error('出现错误'); // 抛出错误
  })
  .then(
    (value) => {
      console.log('这里不会执行'); // 不会执行
    },
    (error) => {
      console.log('捕获错误:', error.message); // 输出: 捕获错误: 出现错误
      return '错误已处理'; // 恢复正常
    }
  )
  .then((value) => {
    console.log('继续执行:', value); // 输出: 继续执行: 错误已处理
  })
  .catch((error) => {
    console.log('这里不会执行'); // 不会执行,因为错误已被处理
  });
🎯 catch 方法的实现原理
// catch 方法的实现
MyPromise.prototype.catch = function (onRejected) {
  return this.then(null, onRejected);
};

为什么 catch 是通过 then 实现的?

  1. 统一处理逻辑:catch 本质上就是只处理错误的 then
  2. 链式调用:catch 也需要返回新的 Promise 以支持链式调用
  3. 错误恢复:catch 处理错误后,也遵循相同的恢复机制
📊 错误处理的四种情况
// 情况1:错误被成功处理(恢复)
Promise.reject('错误')
  .catch((error) => {
    return '已修复'; // 正常返回 → fulfilled
  })
  .then((value) => console.log('恢复:', value));

// 情况2:处理错误时又出现新错误(继续传播)
Promise.reject('错误')
  .catch((error) => {
    throw new Error('处理时出错'); // 抛出异常 → rejected
  })
  .catch((error) => console.log('新错误:', error.message));

// 情况3:错误未被处理(继续传播)
Promise.reject('错误')
  .then((value) => {
    // 没有onRejected处理器
    return value + '处理';
  })
  .catch((error) => console.log('最终捕获:', error));

// 情况4:正常值经过错误处理器
Promise.resolve('正常值')
  .catch((error) => {
    console.log('这里不会执行'); // onRejected不会被调用
    return '错误处理';
  })
  .then((value) => console.log('继续:', value)); // 输出: 继续: 正常值
🔧 then 方法中错误处理的完整逻辑
then(onFulfilled, onRejected) {
  return new MyPromise((resolve, reject) => {
    if (this.state === FULFILLED) {
      try {
        const result = onFulfilled(this.value);
        resolve(result); // 正常执行 → fulfilled
      } catch (error) {
        reject(error); // 执行出错 → rejected
      }
    }

    if (this.state === REJECTED) {
      try {
        const result = onRejected(this.reason);
        resolve(result); // 错误被处理 → fulfilled (恢复)
      } catch (error) {
        reject(error); // 处理出错 → rejected (继续传播)
      }
    }
  });
}
💡 关键理解要点
  1. 错误恢复机制:Promise 的设计哲学是"错误可以被修复"
  2. 处理即恢复:只要错误处理函数正常执行,Promise 链就会恢复
  3. catch 的本质:catch 就是 then(null, onRejected) 的语法糖
  4. 链式传播:错误会沿着 Promise 链传播,直到被处理或到达链末尾
🔍 实际应用示例
// 网络请求错误处理示例
function fetchData(url) {
  return fetch(url)
    .then((response) => {
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      return response.json();
    })
    .catch((error) => {
      console.log('网络错误:', error.message);
      return { error: true, message: '请求失败' }; // 错误恢复
    })
    .then((data) => {
      // 这里会执行,data 可能是正常数据或错误恢复数据
      console.log('最终数据:', data);
      return data;
    });
}

总结:Promise 的错误处理机制设计得非常优雅,它允许错误在链中传播,同时也允许在任何环节进行恢复。这种设计使得异步错误处理变得可预测和可控制。

11.2 then 方法中的回调数组疑问

常见疑问:在 then 方法中,为什么会有这样的代码?

then(onFulfilled) {
  if (this.state === FULFILLED) {
    onFulfilled(this.value); // 这里直接执行了回调
  }
  if (this.state === PENDING) {
    // 但是我们之前保存的数组呢?
    this.onFulfilledCallbacks.push(() => {
      onFulfilled(this.value);
    });
  }
}

详细解释

两种不同的执行路径
// 场景1:Promise已经完成
const resolvedPromise = Promise.resolve('已完成');
resolvedPromise.then((value) => {
  console.log(value); // 直接执行,因为状态已经是FULFILLED
});

// 场景2:Promise还在等待
const pendingPromise = new Promise((resolve) => {
  setTimeout(() => resolve('等待完成'), 1000);
});
pendingPromise.then((value) => {
  console.log(value); // 需要保存到数组,等resolve调用时执行
});
完整的执行流程
class MyPromise {
  constructor(executor) {
    this.state = PENDING;
    this.value = undefined;
    this.onFulfilledCallbacks = []; // 保存等待的回调

    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = FULFILLED;
        this.value = value;
        // 执行所有等待的回调
        this.onFulfilledCallbacks.forEach((callback) => callback());
      }
    };

    executor(resolve, reject);
  }

  then(onFulfilled) {
    // 情况1:已经完成,直接执行
    if (this.state === FULFILLED) {
      onFulfilled(this.value);
      return; // 不需要保存到数组
    }

    // 情况2:还在等待,保存到数组
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        onFulfilled(this.value); // 这个会在resolve时执行
      });
    }
  }
}
关键理解
  1. 数组的作用:只有在 Promise 还是 pending 状态时才需要保存回调
  2. 直接执行:如果 Promise 已经 fulfilled,直接执行回调,不需要数组
  3. 时机不同
    • 已完成:立即执行回调
    • 等待中:保存回调,等 resolve 调用时执行
实际执行示例
// 创建一个异步Promise
const promise = new MyPromise((resolve) => {
  setTimeout(() => {
    console.log('resolve被调用');
    resolve('成功');
  }, 1000);
});

// 第一个then - Promise还是pending
promise.then((value) => {
  console.log('第一个回调:', value);
}); // 这个回调被保存到数组

// 第二个then - Promise还是pending
promise.then((value) => {
  console.log('第二个回调:', value);
}); // 这个回调也被保存到数组

// 此时 onFulfilledCallbacks = [callback1, callback2]

// 1秒后,resolve执行:
// 1. 改变状态为FULFILLED
// 2. 设置值为'成功'
// 3. 执行数组中的所有回调
//    - callback1() -> 输出 '第一个回调: 成功'
//    - callback2() -> 输出 '第二个回调: 成功'

总结:回调数组和直接执行是两种不同的处理方式,取决于 Promise 的当前状态。这样设计确保了无论何时调用 then,都能正确处理回调函数。

11.3 then 方法返回 Promise 的疑问

常见疑问:“Promise 的核心特性之一是链式调用,每个 then 方法都应该返回一个新的 Promise。那为啥 pending 的时候 then 不用返回呢”

🚨 重要澄清

这里有一个关键误解需要澄清:无论 Promise 是什么状态,then 方法都必须返回一个新的 Promise!

让我们看看正确的实现:

❌ 错误的理解(早期简化版本)
// 第二章和第三章的简化版本(仅用于教学)
then(onFulfilled, onRejected) {
  if (this.state === FULFILLED) {
    onFulfilled(this.value); // 直接执行,没有返回Promise
  }

  if (this.state === REJECTED) {
    onRejected(this.reason); // 直接执行,没有返回Promise
  }

  // 处理pending状态
  if (this.state === PENDING) {
    this.onFulfilledCallbacks.push(() => {
      onFulfilled(this.value);
    });
    // 这里也没有返回Promise!
  }
}
✅ 正确的实现(完整版本)
// 第四章开始的正确实现
then(onFulfilled, onRejected) {
  // 无论什么状态,都必须返回新的Promise
  return new MyPromise((resolve, reject) => {
    if (this.state === FULFILLED) {
      try {
        const result = onFulfilled(this.value);
        resolve(result); // 将结果传递给新Promise
      } catch (error) {
        reject(error);
      }
    }

    if (this.state === REJECTED) {
      try {
        const result = onRejected(this.reason);
        resolve(result);
      } catch (error) {
        reject(error);
      }
    }

    // pending状态也要返回Promise
    if (this.state === PENDING) {
      this.onFulfilledCallbacks.push(() => {
        try {
          const result = onFulfilled(this.value);
          resolve(result); // 同样传递给新Promise
        } catch (error) {
          reject(error);
        }
      });

      this.onRejectedCallbacks.push(() => {
        try {
          const result = onRejected(this.reason);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      });
    }
  }); // 这里返回新的Promise
}
🔍 为什么会产生误解?
  1. 教学渐进性:文章从简单版本开始,逐步完善
  2. 早期版本:第二、三章的简化实现确实没有返回 Promise
  3. 状态处理差异:pending 状态的处理看起来"不一样"
📋 关键理解要点
// 无论什么情况,then都返回新Promise
const promise1 = new MyPromise((resolve) => {
  setTimeout(() => resolve('异步结果'), 1000);
});

// 这三个调用都会返回新的Promise实例
const promise2 = promise1.then((value) => value + '1'); // pending时调用
const promise3 = promise1.then((value) => value + '2'); // pending时调用

// 1秒后,promise1变为fulfilled
// 此时再调用then,仍然返回新Promise
setTimeout(() => {
  const promise4 = promise1.then((value) => value + '3'); // fulfilled时调用
}, 1500);
🎯 Promise A+规范要求

根据 Promise A+规范:

2.2.7: then must return a promise

promise2 = promise1.then(onFulfilled, onRejected);

这意味着:

  • 每次调用 then 都必须返回新 Promise
  • 无论原 Promise 是什么状态
  • 这是链式调用的基础
🔄 完整的执行流程对比
// 场景1:Promise已经fulfilled
const resolvedPromise = MyPromise.resolve('已完成');
const newPromise1 = resolvedPromise.then((value) => {
  return value + '处理';
}); // 返回新Promise,立即处理

// 场景2:Promise还是pending
const pendingPromise = new MyPromise((resolve) => {
  setTimeout(() => resolve('等待完成'), 1000);
});
const newPromise2 = pendingPromise.then((value) => {
  return value + '处理';
}); // 返回新Promise,回调被收集

// 关键:两种情况都返回了新的Promise实例!
console.log(newPromise1 instanceof MyPromise); // true
console.log(newPromise2 instanceof MyPromise); // true
💡 为什么必须返回 Promise?
  1. 链式调用promise.then().then().catch()
  2. 状态传播:每个 then 的结果需要传递给下一个
  3. 错误处理:异常需要能够传播到 catch
  4. 规范一致性:Promise A+规范的强制要求
🚀 实际验证
const promise = new MyPromise((resolve) => {
  setTimeout(() => resolve(1), 1000);
});

// 这样的链式调用必须每个then都返回Promise
promise
  .then((value) => {
    console.log('第一步:', value); // 1
    return value + 1;
  })
  .then((value) => {
    console.log('第二步:', value); // 2
    return value * 2;
  })
  .then((value) => {
    console.log('第三步:', value); // 4
  });

// 如果pending时的then不返回Promise,这个链式调用就会失败!

总结:then 方法在任何状态下都必须返回新的 Promise,这是 Promise A+规范的核心要求。pending 状态下的处理只是回调的收集方式不同,但返回 Promise 的要求是一致的。文章早期的简化版本可能造成了误解,但完整实现中这一点是严格遵循的。

11.4 then 是一切的基础 - Promise 设计哲学深度解析

一个极其深刻的观察:“为啥 reject 也是返回 then 状态的 promise 呢,finally 也是,啥都是 then 传递的啊?貌似,then 是一切的基础啊?”

这个观察完全正确!让我们深入探讨 Promise 的设计哲学。

🎯 then 方法的核心地位

在 Promise A+规范中,then 方法是唯一被规范定义的方法!所有其他方法(catch、finally、resolve、reject 等)都是基于 then 方法的扩展实现。

// Promise A+规范只定义了 then 方法
// 其他所有方法都是语法糖或扩展
class MyPromise {
  // 核心方法:规范定义的唯一方法
  then(onFulfilled, onRejected) {
    // 这是 Promise 的核心实现
    return new MyPromise((resolve, reject) => {
      // 所有的状态处理逻辑
    });
  }

  // 以下都是基于 then 的扩展方法
  catch(onRejected) {
    return this.then(null, onRejected); // 基于 then 实现
  }

  finally(onFinally) {
    return this.then(
      (value) => MyPromise.resolve(onFinally()).then(() => value),
      (reason) =>
        MyPromise.resolve(onFinally()).then(() => {
          throw reason;
        })
    ); // 基于 then 实现
  }

  static resolve(value) {
    return new MyPromise((resolve) => resolve(value)); // 创建新 Promise
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => reject(reason)); // 创建新 Promise
  }
}
🔍 为什么 then 是基础?
1. 统一的状态转换机制
// 无论什么操作,最终都要通过 then 来处理状态转换
Promise.resolve('成功')
  .then((value) => value + '1') // fulfilled -> fulfilled
  .catch((error) => '错误处理') // rejected -> fulfilled (错误恢复)
  .finally(() => '清理') // 任何状态 -> 保持原状态
  .then((value) => console.log(value));

// 每一步都返回新的 Promise,都通过 then 的逻辑处理
2. 链式调用的统一接口
// 所有方法都返回 Promise,所以都能继续链式调用
promise
  .then(handleSuccess) // 返回 Promise
  .catch(handleError) // 返回 Promise (基于 then 实现)
  .finally(cleanup) // 返回 Promise (基于 then 实现)
  .then(finalStep); // 继续链式调用
📋 深度解析:为什么 reject 处理后会 resolve?

这是 Promise 错误恢复机制的核心设计:

// 错误处理的本质:错误被处理后,Promise 链恢复正常
Promise.reject('原始错误')
  .then(
    null, // onFulfilled
    (error) => {
      console.log('处理错误:', error);
      return '错误已修复'; // 返回正常值
    }
  )
  .then((value) => {
    console.log('恢复正常:', value); // 输出: 恢复正常: 错误已修复
  });

关键理解

  • onRejected 处理器的作用是"修复"错误
  • 如果修复成功(正常返回值),Promise 链恢复到 fulfilled 状态
  • 只有修复过程中又出现错误,才会继续保持 rejected 状态
🔄 then 方法的统一处理逻辑
then(onFulfilled, onRejected) {
  return new MyPromise((resolve, reject) => {
    // 统一的处理模式:
    // 1. 执行对应的处理器
    // 2. 根据执行结果决定新 Promise 的状态

    if (this.state === FULFILLED) {
      try {
        const result = onFulfilled(this.value);
        resolve(result); // 正常执行 -> fulfilled
      } catch (error) {
        reject(error);   // 执行出错 -> rejected
      }
    }

    if (this.state === REJECTED) {
      try {
        const result = onRejected(this.reason);
        resolve(result); // 错误被处理 -> fulfilled (恢复)
      } catch (error) {
        reject(error);   // 处理出错 -> rejected (继续传播)
      }
    }
  });
}
🎨 设计哲学:一致性原则
1. 状态处理的一致性
// 无论是成功还是失败,处理逻辑都是一致的:
// 执行处理器 -> 根据结果决定新状态

// 成功处理
.then(value => {
  return processValue(value); // 正常返回 -> fulfilled
  // throw error;             // 抛出异常 -> rejected
})

// 失败处理
.catch(error => {
  return fixError(error);     // 正常返回 -> fulfilled (恢复)
  // throw newError;          // 抛出异常 -> rejected (继续)
})
2. 返回值处理的一致性
// 所有方法都遵循相同的返回值处理规则
function handleReturnValue(result) {
  if (result instanceof Promise) {
    // 返回 Promise -> 等待其完成
    return result;
  } else if (isThenable(result)) {
    // 返回 thenable -> 调用其 then 方法
    return new Promise((resolve, reject) => {
      result.then(resolve, reject);
    });
  } else {
    // 返回普通值 -> 直接 resolve
    return Promise.resolve(result);
  }
}
🌟 实际应用中的体现
1. catch 就是特殊的 then
// 这两种写法完全等价
promise.catch(handleError);
promise.then(null, handleError);

// catch 的实现
catch(onRejected) {
  return this.then(null, onRejected);
}
2. finally 通过 then 实现状态透传
// finally 的巧妙实现
finally(onFinally) {
  return this.then(
    // 成功时:执行 finally,但保持原值
    value => Promise.resolve(onFinally()).then(() => value),
    // 失败时:执行 finally,但保持原错误
    reason => Promise.resolve(onFinally()).then(() => { throw reason; })
  );
}

// 使用示例
promise
  .then(value => value * 2)
  .finally(() => console.log('清理工作')) // 不改变值,只执行副作用
  .then(value => console.log('最终值:', value)); // 仍然是原来的值
3. 静态方法也依赖 then 的机制
// Promise.all 的实现也是基于 then
Promise.all = function (promises) {
  return new Promise((resolve, reject) => {
    // 每个 promise 都通过 then 来处理
    promises.forEach((promise, index) => {
      Promise.resolve(promise).then(
        (value) => {
          /* 收集结果 */
        },
        reject // 任何一个失败就整体失败
      );
    });
  });
};
💡 深层设计原理
1. 单一职责原则
// then 方法承担唯一职责:状态转换和值传递
// 其他方法都是特定场景的封装

// 专门处理错误
.catch(error => handleError(error))

// 专门处理清理
.finally(() => cleanup())

// 但本质上都是 then 的特殊用法
2. 组合优于继承
// Promise 的强大来自于 then 方法的组合能力
promise
  .then(step1) // 第一步处理
  .then(step2) // 第二步处理
  .catch(handleError) // 错误处理
  .finally(cleanup) // 清理工作
  .then(finalStep); // 最终处理

// 每个环节都是独立的,可以自由组合
3. 可预测的行为
// 无论多复杂的 Promise 链,都遵循相同的规则
// 这使得异步代码变得可预测和可维护

async function complexAsyncFlow() {
  return fetchData()
    .then(validateData) // 验证数据
    .catch(handleValidationError) // 处理验证错误
    .then(processData) // 处理数据
    .catch(handleProcessError) // 处理处理错误
    .finally(cleanup) // 清理资源
    .then(formatResult); // 格式化结果
}
🔧 实现细节的统一性
// 所有 Promise 方法的实现都遵循相同的模式
class MyPromise {
  // 核心方法
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      // 统一的异步执行和错误处理
      this.handleCallback(onFulfilled, onRejected, resolve, reject);
    });
  }

  // 扩展方法都基于 then
  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(onFinally) {
    return this.then(
      (value) => MyPromise.resolve(onFinally()).then(() => value),
      (reason) =>
        MyPromise.resolve(onFinally()).then(() => {
          throw reason;
        })
    );
  }

  // 静态方法也创建基于 then 的 Promise
  static resolve(value) {
    return new MyPromise((resolve) => resolve(value));
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => reject(reason));
  }
}
🎯 核心理解要点
  1. then 是 Promise 的唯一核心方法:Promise A+规范只定义了 then 方法
  2. 所有其他方法都是语法糖:catch、finally、resolve、reject 等都基于 then 实现
  3. 统一的状态转换机制:无论成功还是失败,都通过相同的逻辑处理
  4. 错误恢复设计:错误处理器的目的是修复错误,成功修复后恢复正常流程
  5. 链式调用的基础:每个方法都返回 Promise,支持无限链式调用
  6. 可组合的设计:通过 then 的组合实现复杂的异步流程控制
🌈 设计的优雅之处
// Promise 的设计让异步代码变得像同步代码一样直观
getData()
  .then((data) => validateData(data)) // 验证
  .then((data) => transformData(data)) // 转换
  .then((data) => saveData(data)) // 保存
  .catch((error) => handleError(error)) // 统一错误处理
  .finally(() => hideLoading()); // 清理工作

// 每一步都是可预测的,错误会自动传播到 catch
// 这种设计让复杂的异步流程变得简单和可维护

总结:这个观察完全正确!then 确实是 Promise 的一切基础。这种设计体现了优秀的软件架构原则:通过一个强大而简洁的核心机制(then),支撑起整个异步编程体系。所有其他方法都是基于 then 的扩展和封装,这使得 Promise 既强大又一致,既灵活又可预测。这就是为什么理解 then 方法的实现原理如此重要——它是理解整个 Promise 体系的关键。

总结

通过本文的逐步实现,我们完成了一个符合 Promise A+规范的 Promise 实现。关键要点包括:

核心概念

  1. 状态管理:pending、fulfilled、rejected 三种状态的正确转换
  2. 异步处理:通过回调数组处理异步操作
  3. 链式调用:每个 then 方法返回新的 Promise 实例
  4. 值的解析:正确处理返回值的各种情况

关键技术点

  1. resolvePromise 函数:处理 Promise 值解析的核心逻辑
  2. 异步执行:确保回调函数异步执行
  3. 错误处理:完善的异常捕获和传播机制
  4. 循环引用检测:避免 Promise 链的循环引用

扩展功能

  1. 静态方法:resolve、reject、all、race 等
  2. 实例方法:catch、finally 等
  3. 性能优化:微任务队列、内存管理等

这个实现不仅帮助理解 Promise 的工作原理,也为深入学习异步编程和 JavaScript 引擎机制奠定了基础。在实际项目中,建议使用原生 Promise 或成熟的 polyfill 库,但理解其实现原理对于编写高质量的异步代码非常重要。

附录:高级前端技能评估

关于技能层次的思考

掌握 Promise A+ 规范实现确实是高级前端的重要技能之一,但这只是冰山一角。让我们来看看不同层次的前端技能要求:

🎯 中级前端 (2-4 年)
  • 基础使用:熟练使用 Promise、async/await
  • 常见场景:处理异步请求、错误处理、Promise.all/race
  • 框架应用:在 React/Vue 中正确使用异步操作
🚀 高级前端 (4-7 年)
  • 深度理解:理解 Promise A+ 规范,能手写实现
  • 性能优化:微任务队列、事件循环机制
  • 架构设计:异步流程控制、错误边界设计
  • 源码阅读:能读懂主流库的异步实现
🏆 资深前端 (7 年+)
  • 底层原理:V8 引擎异步机制、内存管理
  • 技术创新:设计异步编程模式、工具库
  • 团队影响:制定异步编程规范、技术分享

高级前端面试会问什么?

高级前端面试更偏重实际场景题,而不是纯粹的理论实现。让我们看看真实的面试场景:

🎯 实际业务场景题
// 1. 锁屏30秒后自动登出
class ScreenLockManager {
  constructor(lockTime = 30000) {
    this.lockTime = lockTime;
    this.lockTimer = null;
    this.isLocked = false;
    this.listeners = [];

    this.init();
  }

  init() {
    // 监听用户活动
    const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
    events.forEach((event) => {
      document.addEventListener(event, this.resetTimer.bind(this), true);
    });

    // 监听页面可见性变化
    document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this));

    this.resetTimer();
  }

  resetTimer() {
    if (this.isLocked) return;

    clearTimeout(this.lockTimer);
    this.lockTimer = setTimeout(() => {
      this.lockScreen();
    }, this.lockTime);
  }

  lockScreen() {
    this.isLocked = true;
    this.notifyListeners('lock');

    // 自动登出逻辑
    return this.autoLogout();
  }

  async autoLogout() {
    try {
      // 保存当前状态
      await this.saveUserState();

      // 清除敏感数据
      this.clearSensitiveData();

      // 跳转到登录页
      window.location.href = '/login';
    } catch (error) {
      console.error('自动登出失败:', error);
    }
  }

  async saveUserState() {
    const state = {
      currentPath: window.location.pathname,
      timestamp: Date.now(),
      formData: this.collectFormData()
    };

    return new Promise((resolve) => {
      localStorage.setItem('userState', JSON.stringify(state));
      resolve();
    });
  }

  clearSensitiveData() {
    // 清除token
    localStorage.removeItem('authToken');
    sessionStorage.clear();

    // 清除cookie
    document.cookie.split(';').forEach((cookie) => {
      const eqPos = cookie.indexOf('=');
      const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
      document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/';
    });
  }

  unlock(password) {
    return new Promise((resolve, reject) => {
      // 验证密码
      this.validatePassword(password)
        .then(() => {
          this.isLocked = false;
          this.resetTimer();
          this.notifyListeners('unlock');
          resolve();
        })
        .catch(reject);
    });
  }

  onStateChange(callback) {
    this.listeners.push(callback);
  }

  notifyListeners(state) {
    this.listeners.forEach((callback) => callback(state));
  }
}

// 2. 防抖搜索 + 缓存 + 取消请求
class SmartSearch {
  constructor(searchFn, options = {}) {
    this.searchFn = searchFn;
    this.debounceTime = options.debounceTime || 300;
    this.cacheSize = options.cacheSize || 100;
    this.cache = new Map();
    this.pendingRequest = null;
    this.debounceTimer = null;
  }

  async search(query) {
    // 取消之前的请求
    if (this.pendingRequest) {
      this.pendingRequest.cancel();
    }

    // 清除防抖定时器
    clearTimeout(this.debounceTimer);

    // 检查缓存
    if (this.cache.has(query)) {
      return this.cache.get(query);
    }

    return new Promise((resolve, reject) => {
      this.debounceTimer = setTimeout(async () => {
        try {
          // 创建可取消的请求
          this.pendingRequest = this.createCancelableRequest(query);
          const result = await this.pendingRequest.promise;

          // 缓存结果
          this.cacheResult(query, result);

          resolve(result);
        } catch (error) {
          if (error.name !== 'CancelError') {
            reject(error);
          }
        } finally {
          this.pendingRequest = null;
        }
      }, this.debounceTime);
    });
  }

  createCancelableRequest(query) {
    let isCanceled = false;

    const promise = new Promise(async (resolve, reject) => {
      try {
        const result = await this.searchFn(query);
        if (!isCanceled) {
          resolve(result);
        }
      } catch (error) {
        if (!isCanceled) {
          reject(error);
        }
      }
    });

    return {
      promise,
      cancel: () => {
        isCanceled = true;
        const error = new Error('Request canceled');
        error.name = 'CancelError';
        throw error;
      }
    };
  }

  cacheResult(query, result) {
    // LRU缓存策略
    if (this.cache.size >= this.cacheSize) {
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
    this.cache.set(query, result);
  }
}

// 3. 实时数据同步(WebSocket + 断线重连)
class RealTimeDataSync {
  constructor(url, options = {}) {
    this.url = url;
    this.options = {
      reconnectInterval: 5000,
      maxReconnectAttempts: 10,
      heartbeatInterval: 30000,
      ...options
    };

    this.ws = null;
    this.reconnectAttempts = 0;
    this.isConnecting = false;
    this.messageQueue = [];
    this.subscribers = new Map();
    this.heartbeatTimer = null;

    this.connect();
  }

  async connect() {
    if (this.isConnecting) return;

    this.isConnecting = true;

    try {
      this.ws = new WebSocket(this.url);

      this.ws.onopen = () => {
        console.log('WebSocket连接成功');
        this.isConnecting = false;
        this.reconnectAttempts = 0;

        // 发送队列中的消息
        this.flushMessageQueue();

        // 开始心跳
        this.startHeartbeat();

        this.emit('connected');
      };

      this.ws.onmessage = (event) => {
        const data = JSON.parse(event.data);

        if (data.type === 'pong') {
          // 心跳响应
          return;
        }

        this.emit('message', data);
      };

      this.ws.onclose = () => {
        console.log('WebSocket连接关闭');
        this.cleanup();
        this.scheduleReconnect();
      };

      this.ws.onerror = (error) => {
        console.error('WebSocket错误:', error);
        this.emit('error', error);
      };
    } catch (error) {
      this.isConnecting = false;
      this.scheduleReconnect();
    }
  }

  scheduleReconnect() {
    if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
      this.emit('maxReconnectAttemptsReached');
      return;
    }

    this.reconnectAttempts++;

    setTimeout(() => {
      console.log(`尝试重连 (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})`);
      this.connect();
    }, this.options.reconnectInterval * this.reconnectAttempts);
  }

  send(data) {
    const message = JSON.stringify(data);

    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(message);
    } else {
      // 连接未就绪,加入队列
      this.messageQueue.push(message);
    }
  }

  flushMessageQueue() {
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift();
      this.ws.send(message);
    }
  }

  startHeartbeat() {
    this.heartbeatTimer = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify({ type: 'ping' }));
      }
    }, this.options.heartbeatInterval);
  }

  cleanup() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  subscribe(event, callback) {
    if (!this.subscribers.has(event)) {
      this.subscribers.set(event, []);
    }
    this.subscribers.get(event).push(callback);
  }

  emit(event, data) {
    const callbacks = this.subscribers.get(event) || [];
    callbacks.forEach((callback) => callback(data));
  }

  disconnect() {
    this.cleanup();
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }
}
📋 Promise 相关深度问题
// 1. 实现 Promise.allSettled
Promise.myAllSettled = function (promises) {
  return Promise.all(
    promises.map((promise) =>
      Promise.resolve(promise)
        .then((value) => ({ status: 'fulfilled', value }))
        .catch((reason) => ({ status: 'rejected', reason }))
    )
  );
};

// 2. 实现带并发控制的 Promise.all
function promiseAllWithLimit(promises, limit) {
  return new Promise((resolve, reject) => {
    const results = [];
    let index = 0;
    let running = 0;
    let finished = 0;

    function next() {
      if (index >= promises.length) return;

      const currentIndex = index++;
      running++;

      Promise.resolve(promises[currentIndex])
        .then((result) => {
          results[currentIndex] = result;
          finished++;
          running--;

          if (finished === promises.length) {
            resolve(results);
          } else {
            next();
          }
        })
        .catch(reject);
    }

    // 启动初始并发
    for (let i = 0; i < Math.min(limit, promises.length); i++) {
      next();
    }
  });
}

// 3. 实现 Promise 重试机制
function retryPromise(promiseFactory, maxRetries = 3, delay = 1000) {
  return new Promise((resolve, reject) => {
    let attempts = 0;

    function attempt() {
      attempts++;
      promiseFactory()
        .then(resolve)
        .catch((error) => {
          if (attempts >= maxRetries) {
            reject(error);
          } else {
            setTimeout(attempt, delay * attempts); // 指数退避
          }
        });
    }

    attempt();
  });
}
🔧 事件循环与异步机制
// 4. 分析执行顺序
console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => {
  console.log('3');
  setTimeout(() => console.log('4'), 0);
});

new Promise((resolve) => {
  console.log('5');
  resolve();
}).then(() => console.log('6'));

console.log('7');

// 答案:1, 5, 7, 3, 6, 2, 4

// 5. 实现 scheduler 调度器
class Scheduler {
  constructor(maxConcurrency = 2) {
    this.maxConcurrency = maxConcurrency;
    this.running = 0;
    this.queue = [];
  }

  add(promiseFactory) {
    return new Promise((resolve, reject) => {
      this.queue.push({
        promiseFactory,
        resolve,
        reject
      });
      this.process();
    });
  }

  process() {
    if (this.running >= this.maxConcurrency || this.queue.length === 0) {
      return;
    }

    this.running++;
    const { promiseFactory, resolve, reject } = this.queue.shift();

    promiseFactory()
      .then(resolve)
      .catch(reject)
      .finally(() => {
        this.running--;
        this.process();
      });
  }
}
🏗️ 架构设计问题
// 6. 设计一个支持取消的 Promise
class CancelablePromise {
  constructor(executor) {
    this.isCanceled = false;
    this.cancelReason = null;

    this.promise = new Promise((resolve, reject) => {
      this.reject = reject;

      const wrappedResolve = (value) => {
        if (!this.isCanceled) resolve(value);
      };

      const wrappedReject = (reason) => {
        if (!this.isCanceled) reject(reason);
      };

      executor(wrappedResolve, wrappedReject);
    });
  }

  cancel(reason = 'Promise was canceled') {
    if (!this.isCanceled) {
      this.isCanceled = true;
      this.cancelReason = reason;
      this.reject(new Error(reason));
    }
  }

  then(onFulfilled, onRejected) {
    return this.promise.then(onFulfilled, onRejected);
  }

  catch(onRejected) {
    return this.promise.catch(onRejected);
  }
}

// 7. 实现 Promise 管道
function pipe(...fns) {
  return function (value) {
    return fns.reduce((promise, fn) => {
      return promise.then(fn);
    }, Promise.resolve(value));
  };
}

// 使用示例
const pipeline = pipe(
  (x) => x * 2,
  (x) => Promise.resolve(x + 1),
  (x) => x * 3
);

pipeline(5).then(console.log); // 33
🧠 性能与内存优化
// 8. 内存泄漏检测
class PromiseLeakDetector {
  constructor() {
    this.activePromises = new WeakSet();
    this.promiseCount = 0;
  }

  createPromise(executor) {
    this.promiseCount++;
    const promise = new Promise(executor);
    this.activePromises.add(promise);

    // 监控 Promise 完成
    promise.finally(() => {
      this.promiseCount--;
    });

    return promise;
  }

  getActiveCount() {
    return this.promiseCount;
  }
}

// 9. 实现 Promise 池
class PromisePool {
  constructor(concurrency = 3) {
    this.concurrency = concurrency;
    this.running = [];
    this.queue = [];
  }

  async add(promiseFactory) {
    return new Promise((resolve, reject) => {
      this.queue.push({
        promiseFactory,
        resolve,
        reject
      });
      this.process();
    });
  }

  async process() {
    if (this.running.length >= this.concurrency || this.queue.length === 0) {
      return;
    }

    const { promiseFactory, resolve, reject } = this.queue.shift();
    const promise = promiseFactory()
      .then(resolve)
      .catch(reject)
      .finally(() => {
        this.running.splice(this.running.indexOf(promise), 1);
        this.process();
      });

    this.running.push(promise);
    this.process();
  }
}

🎓 高级前端的其他核心技能

1. JavaScript 引擎原理
  • V8 编译优化、JIT
  • 垃圾回收机制
  • 内存管理策略
2. 框架源码理解
  • React Fiber 架构
  • Vue 响应式原理
  • 状态管理库实现
3. 工程化能力
  • Webpack/Vite 原理
  • Babel 插件开发
  • 构建优化策略
4. 性能优化
  • 首屏优化策略
  • 运行时性能监控
  • 内存泄漏排查
5. 架构设计
  • 微前端架构
  • 组件库设计
  • 跨端解决方案

💡 提升建议

  1. 深度学习:不仅要会用,更要理解原理
  2. 源码阅读:阅读优秀开源项目源码
  3. 实践项目:参与复杂项目的架构设计
  4. 技术分享:通过分享加深理解
  5. 持续学习:关注技术发展趋势

总结:掌握 Promise A+ 实现是高级前端的基础技能,但真正的高级前端需要在深度和广度上都有所建树,能够解决复杂的技术问题,并具备架构设计和团队协作能力。

🎯 面试应对策略:遇到陌生问题不要慌

面试中经常会遇到一些之前没有深入思考过的问题,比如"实现锁屏 30 秒后自动登出",这时候脑子一片空白是很正常的。关键是要有系统性的思考方法。

📋 结构化思考框架

当遇到陌生问题时,可以按照以下步骤来组织思路:

1. 需求分析阶段(30 秒思考时间)
// 面试官问:实现锁屏30秒后自动登出
// 不要急着写代码,先分析需求

// 思考框架:
// 1. 什么是锁屏?
// 2. 如何检测锁屏状态?
// 3. 如何计时30秒?
// 4. 登出需要做什么?
// 5. 有哪些边界情况?

可以这样回答

“这个问题很有意思,让我先理解一下需求。锁屏应该是指用户无操作或者主动锁定屏幕,30 秒后需要自动登出。我需要考虑几个方面:用户活动检测、计时机制、登出流程,还有一些边界情况的处理。”

2. 技术方案设计(边说边想)
// 逐步展开技术方案
class ScreenLockManager {
  constructor() {
    // 先说出核心思路
    console.log(`
    核心思路:
    1. 监听用户活动事件(鼠标、键盘、触摸)
    2. 无活动时启动锁屏计时器
    3. 30秒后执行登出逻辑
    4. 处理页面可见性变化
    `);
  }
}

边写边解释

“我的思路是这样的:首先需要监听用户的活动事件,包括鼠标移动、键盘输入等。当检测到用户无活动时,启动一个 30 秒的计时器。同时还要考虑页面可见性 API,处理用户切换标签页的情况。”

3. 逐步实现(分模块思考)
// 不要一次性写完整代码,分模块实现
class ScreenLockManager {
  constructor(lockTime = 30000) {
    this.lockTime = lockTime;
    this.lockTimer = null;
    this.isLocked = false;

    // 先实现基础框架
    this.initEventListeners();
  }

  // 模块1:事件监听
  initEventListeners() {
    // "首先实现用户活动检测"
    const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
    events.forEach((event) => {
      document.addEventListener(event, this.resetTimer.bind(this), true);
    });
  }

  // 模块2:计时器管理
  resetTimer() {
    // "然后是计时器的重置逻辑"
    if (this.isLocked) return;

    clearTimeout(this.lockTimer);
    this.lockTimer = setTimeout(() => {
      this.lockScreen();
    }, this.lockTime);
  }

  // 模块3:锁屏和登出
  async lockScreen() {
    // "最后是锁屏和登出的处理"
    this.isLocked = true;

    // 可以先说思路,再实现细节
    console.log('需要处理:保存状态、清除敏感数据、跳转登录页');

    try {
      await this.saveUserState();
      this.clearSensitiveData();
      this.redirectToLogin();
    } catch (error) {
      console.error('登出失败:', error);
    }
  }
}
4. 边界情况和优化(展示思考深度)
// 展示对边界情况的考虑
class ScreenLockManager {
  // "还需要考虑一些边界情况"

  handleVisibilityChange() {
    // 页面隐藏时的处理
    if (document.hidden) {
      // 页面隐藏时可能需要立即锁屏或者暂停计时
    }
  }

  handleBeforeUnload() {
    // 页面关闭前的清理工作
    this.cleanup();
  }

  // 防抖优化
  resetTimer = debounce(() => {
    // 避免频繁重置计时器
  }, 100);
}
🗣️ 面试沟通技巧
1. 争取思考时间
// 好的回应方式:
"这是一个很实际的业务场景,让我先梳理一下思路..."
"我需要考虑几个关键点,给我30秒整理一下..."
"这个问题涉及多个方面,我先分析一下需求..."

// 避免的回应:
"呃...这个...我没做过..."
"不知道怎么实现..."
直接开始写代码(没有思考过程)
2. 展示思考过程
// 边想边说的技巧:
'首先我需要确定什么算是用户活动...';
'然后考虑计时器的管理,这里可能需要防抖...';
'登出的时候需要清理哪些数据呢...';
'还要考虑用户体验,比如给出提示...';

// 展示技术深度:
'这里可能需要考虑内存泄漏的问题...';
'如果是SPA应用,路由跳转也需要处理...';
'移动端还要考虑触摸事件的兼容性...';
3. 承认不足并展示学习能力
// 诚实但积极的回应:
'这个具体的API我记得不太清楚,但我知道大概的思路是...';
'我之前没有完整实现过,但我觉得核心应该是...';
'如果是生产环境,我会先查阅相关文档确保实现的准确性...';

// 展示解决问题的能力:
'我会这样去解决这个问题:首先查阅MDN文档...';
'我可能会参考一些成熟的库的实现方式...';
'我会写一些测试用例来验证边界情况...';
🧠 快速学习和应用的方法
1. 建立知识框架
// 平时积累的思维模式
const problemSolvingFramework = {
  // 用户交互类问题
  userInteraction: {
    eventListening: '事件监听和处理',
    stateManagement: '状态管理',
    userExperience: '用户体验优化'
  },

  // 异步处理类问题
  asyncProcessing: {
    timing: '定时器和延迟',
    promises: 'Promise和异步流程',
    errorHandling: '错误处理和恢复'
  },

  // 数据安全类问题
  dataSecurity: {
    storage: '数据存储和清理',
    authentication: '身份验证',
    encryption: '加密和解密'
  }
};
2. 常见模式的快速应用
// 观察者模式 - 适用于状态变化通知
class EventEmitter {
  constructor() {
    this.listeners = new Map();
  }

  on(event, callback) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event).push(callback);
  }

  emit(event, data) {
    const callbacks = this.listeners.get(event) || [];
    callbacks.forEach((callback) => callback(data));
  }
}

// 单例模式 - 适用于全局状态管理
class LockManager {
  static instance = null;

  static getInstance() {
    if (!LockManager.instance) {
      LockManager.instance = new LockManager();
    }
    return LockManager.instance;
  }
}

// 策略模式 - 适用于多种处理方式
class LogoutStrategy {
  static strategies = {
    immediate: () => {
      /* 立即登出 */
    },
    graceful: () => {
      /* 优雅登出 */
    },
    withConfirm: () => {
      /* 确认后登出 */
    }
  };

  static execute(type, context) {
    return this.strategies[type](context);
  }
}
💡 心理调节技巧
1. 正确的心态
// 面试不是考试,是技术交流
const mindset = {
  // ✅ 正确心态
  collaboration: '和面试官一起解决问题',
  learning: '展示学习能力和思考过程',
  communication: '重视沟通和表达能力',

  // ❌ 错误心态
  perfectionism: '必须写出完美的代码',
  competition: '和面试官较劲',
  silence: '不会就保持沉默'
};
2. 缓解紧张的方法
// 面试前的准备
const preparation = {
  technical: {
    reviewBasics: '复习基础知识',
    practiceProblems: '练习常见问题',
    prepareQuestions: '准备要问的问题'
  },

  mental: {
    deepBreathing: '深呼吸放松',
    positiveThinking: '积极心理暗示',
    mockInterview: '模拟面试练习'
  }
};

// 面试中的应对
const duringInterview = {
  stayCalm: '保持冷静,慢慢思考',
  askQuestions: '主动询问需求细节',
  showProcess: '展示思考过程',
  admitLimits: '诚实承认不足'
};
🎯 实战演练建议
1. 日常练习方法
// 建立问题库和解决方案
const practiceRoutine = {
  daily: {
    codeReview: '每天看一些优秀代码',
    problemSolving: '解决一个小问题',
    conceptReview: '复习一个技术概念'
  },

  weekly: {
    mockInterview: '模拟面试练习',
    projectAnalysis: '分析开源项目',
    technologyResearch: '研究新技术'
  },

  monthly: {
    knowledgeMapping: '整理知识体系',
    skillAssessment: '评估技能水平',
    careerPlanning: '规划学习方向'
  }
};
2. 建立个人知识库
// 按场景分类的解决方案
const knowledgeBase = {
  userInteraction: {
    eventHandling: '事件处理最佳实践',
    stateManagement: '状态管理方案',
    performanceOptimization: '性能优化技巧'
  },

  dataProcessing: {
    asyncPatterns: '异步处理模式',
    errorHandling: '错误处理策略',
    caching: '缓存实现方案'
  },

  security: {
    authentication: '身份验证方案',
    dataProtection: '数据保护措施',
    secureStorage: '安全存储实现'
  }
};
🏆 成功案例分析
// 面试成功的关键因素
const successFactors = {
  technicalSkills: {
    fundamentals: '扎实的基础知识',
    problemSolving: '良好的问题解决能力',
    codeQuality: '清晰的代码表达'
  },

  softSkills: {
    communication: '良好的沟通表达',
    learning: '快速学习适应能力',
    collaboration: '团队协作精神'
  },

  mindset: {
    confidence: '适度的自信',
    humility: '谦逊的学习态度',
    curiosity: '对技术的好奇心'
  }
};

核心要点

  1. 不要慌张 - 给自己时间思考,面试官通常会给予理解
  2. 结构化思考 - 按照需求分析 → 方案设计 → 实现 → 优化的步骤
  3. 展示过程 - 让面试官看到思考过程比完美答案更重要
  4. 诚实沟通 - 承认不足但展示学习能力和解决问题的思路
  5. 平时积累 - 建立知识框架和常见模式的解决方案库

记住,面试是双向选择的过程,展示真实的技术水平和学习能力比硬撑更有价值。