logo

「JS进阶」手写Promise实现:跨年特辑深度解析

作者:梅琳marlin2025.09.19 12:47浏览量:1

简介:本文通过手写Promise核心逻辑,解析异步编程本质,涵盖状态管理、链式调用、错误处理等关键模块,提供可运行的代码实现与调试技巧。

一、Promise核心机制解析

1.1 三态模型与状态不可逆

Promise规范定义了三种状态:pending(初始)、fulfilled(成功)、rejected(失败)。状态转换具有单向性,一旦从pending转为fulfilled/rejected,将永久保持。这种设计避免了竞态条件,确保异步操作的确定性。

  1. class MyPromise {
  2. constructor(executor) {
  3. this.state = 'pending'; // 初始状态
  4. this.value = undefined; // 成功值
  5. this.reason = undefined; // 失败原因
  6. this.onFulfilledCallbacks = []; // 成功回调队列
  7. this.onRejectedCallbacks = []; // 失败回调队列
  8. }
  9. }

1.2 异步任务队列管理

当Promise状态变更时,需要将对应的回调函数推入微任务队列。由于原生环境无法直接操作微任务队列,我们通过setTimeout模拟异步执行,实际开发中可使用queueMicrotaskMutationObserver优化。

  1. const resolve = (value) => {
  2. if (this.state === 'pending') {
  3. this.state = 'fulfilled';
  4. this.value = value;
  5. // 模拟微任务执行
  6. setTimeout(() => {
  7. this.onFulfilledCallbacks.forEach(fn => fn());
  8. }, 0);
  9. }
  10. };

二、链式调用实现原理

2.1 then方法设计

then方法需返回新的Promise实例以实现链式调用。关键在于处理返回值:当回调返回普通值时,新Promise自动resolve;返回Promise时需等待其状态变更。

  1. then(onFulfilled, onRejected) {
  2. const promise2 = new MyPromise((resolve, reject) => {
  3. const handleFulfilled = (value) => {
  4. try {
  5. if (typeof onFulfilled !== 'function') {
  6. resolve(value); // 穿透处理
  7. } else {
  8. const x = onFulfilled(value);
  9. resolvePromise(promise2, x, resolve, reject);
  10. }
  11. } catch (e) {
  12. reject(e);
  13. }
  14. };
  15. // 类似实现handleRejected...
  16. });
  17. return promise2;
  18. }

2.2 resolvePromise规范实现

此函数处理then回调的返回值,需遵循Promise/A+规范中的值穿透和Promise链解析规则:

  1. function resolvePromise(promise2, x, resolve, reject) {
  2. if (promise2 === x) {
  3. return reject(new TypeError('Chaining cycle detected'));
  4. }
  5. let called = false;
  6. if (x instanceof MyPromise) {
  7. x.then(
  8. y => resolvePromise(promise2, y, resolve, reject),
  9. reject
  10. );
  11. } else if (typeof x === 'object' || typeof x === 'function') {
  12. try {
  13. const then = x.then;
  14. if (typeof then === 'function') {
  15. then.call(
  16. x,
  17. y => {
  18. if (called) return;
  19. called = true;
  20. resolvePromise(promise2, y, resolve, reject);
  21. },
  22. reject
  23. );
  24. } else {
  25. resolve(x);
  26. }
  27. } catch (e) {
  28. if (called) return;
  29. called = true;
  30. reject(e);
  31. }
  32. } else {
  33. resolve(x);
  34. }
  35. }

三、跨年场景实用增强

3.1 延迟执行装饰器

在跨年倒计时等场景中,可通过装饰器模式实现延迟执行:

  1. function delayPromise(promise, timeout) {
  2. return new MyPromise((resolve, reject) => {
  3. const timer = setTimeout(() => {
  4. promise.then(resolve, reject);
  5. }, timeout);
  6. promise.then(() => clearTimeout(timer));
  7. });
  8. }
  9. // 使用示例
  10. delayPromise(fetch('https://api.example.com/newyear'), 5000)
  11. .then(console.log);

3.2 并发控制工具

实现类似Promise.all的并发控制,适用于批量请求新年祝福接口:

  1. static all(promises) {
  2. return new MyPromise((resolve, reject) => {
  3. const results = [];
  4. let count = 0;
  5. promises.forEach((promise, index) => {
  6. MyPromise.resolve(promise).then(
  7. value => {
  8. results[index] = value;
  9. if (++count === promises.length) resolve(results);
  10. },
  11. reject
  12. );
  13. });
  14. });
  15. }

四、调试与优化技巧

4.1 状态追踪日志

在开发阶段添加状态变更日志,便于定位异步问题:

  1. class DebugPromise extends MyPromise {
  2. constructor(executor) {
  3. super(executor);
  4. const originalResolve = this.resolve;
  5. this.resolve = (value) => {
  6. console.log(`[DEBUG] Promise resolved with:`, value);
  7. originalResolve.call(this, value);
  8. };
  9. // 类似实现reject的日志...
  10. }
  11. }

4.2 性能优化方案

  1. 回调合并:对于高频触发的Promise(如实时数据流),可采用节流合并回调
  2. 错误边界:在链式调用顶端添加全局错误捕获
  3. 内存管理:及时清理已完成的Promise回调引用

五、完整实现示例

  1. class MyPromise {
  2. // 前文实现代码...
  3. static resolve(value) {
  4. if (value instanceof MyPromise) return value;
  5. return new MyPromise(resolve => resolve(value));
  6. }
  7. static reject(reason) {
  8. return new MyPromise((_, reject) => reject(reason));
  9. }
  10. catch(onRejected) {
  11. return this.then(null, onRejected);
  12. }
  13. finally(onFinally) {
  14. return this.then(
  15. value => MyPromise.resolve(onFinally()).then(() => value),
  16. reason => MyPromise.resolve(onFinally()).then(() => { throw reason; })
  17. );
  18. }
  19. }
  20. // 测试用例
  21. new MyPromise((resolve) => {
  22. setTimeout(() => resolve('新年快乐'), 1000);
  23. })
  24. .then(console.log)
  25. .catch(console.error);

六、学习建议与进阶方向

  1. 规范对比:对照Promise/A+规范实现剩余测试用例
  2. 源码解析:研究V8引擎中Promise的底层实现
  3. 异步模式:结合Generator/Async函数理解Promise的进化路径
  4. 工具开发:尝试实现Promise.race、Promise.any等API

通过系统性的手写实现,开发者不仅能深入理解异步编程原理,更能培养出解决复杂并发问题的能力。这种从底层到上层的认知构建,对于处理高并发场景(如跨年活动流量峰值)具有重要实践价值。

相关文章推荐

发表评论