logo

从零实现Promise:手写核心逻辑与静态方法解析

作者:很菜不狗2025.09.19 12:47浏览量:0

简介:本文深入解析Promise核心机制,通过手写实现帮助开发者理解异步编程原理,重点实现Promise类、all方法及race方法,附带完整代码与测试用例。

从零实现Promise:手写核心逻辑与静态方法解析

Promise作为JavaScript异步编程的核心解决方案,其内部实现机制一直是前端开发者关注的重点。本文将通过手写实现的方式,深入解析Promise的核心逻辑,并重点实现allrace两个静态方法,帮助开发者建立完整的Promise知识体系。

一、Promise核心实现

1.1 基础类结构

一个完整的Promise实现需要包含以下核心要素:

  • 三种状态:pendingfulfilledrejected
  • 状态变更的不可逆性
  • 值/原因的存储
  • 回调队列管理
  • 异步执行机制
  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. const resolve = (value) => {
  9. if (this.state === 'pending') {
  10. this.state = 'fulfilled';
  11. this.value = value;
  12. this.onFulfilledCallbacks.forEach(fn => fn());
  13. }
  14. };
  15. const reject = (reason) => {
  16. if (this.state === 'pending') {
  17. this.state = 'rejected';
  18. this.reason = reason;
  19. this.onRejectedCallbacks.forEach(fn => fn());
  20. }
  21. };
  22. try {
  23. executor(resolve, reject);
  24. } catch (err) {
  25. reject(err);
  26. }
  27. }
  28. }

1.2 then方法实现

then方法是Promise的核心,需要处理:

  • 链式调用
  • 异步执行
  • 回调函数参数传递
  • 状态转换时的回调执行
  1. then(onFulfilled, onRejected) {
  2. // 参数可选处理
  3. onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
  4. onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
  5. const promise2 = new MyPromise((resolve, reject) => {
  6. if (this.state === 'fulfilled') {
  7. setTimeout(() => {
  8. try {
  9. const x = onFulfilled(this.value);
  10. resolvePromise(promise2, x, resolve, reject);
  11. } catch (e) {
  12. reject(e);
  13. }
  14. }, 0);
  15. } else if (this.state === 'rejected') {
  16. setTimeout(() => {
  17. try {
  18. const x = onRejected(this.reason);
  19. resolvePromise(promise2, x, resolve, reject);
  20. } catch (e) {
  21. reject(e);
  22. }
  23. }, 0);
  24. } else if (this.state === 'pending') {
  25. this.onFulfilledCallbacks.push(() => {
  26. setTimeout(() => {
  27. try {
  28. const x = onFulfilled(this.value);
  29. resolvePromise(promise2, x, resolve, reject);
  30. } catch (e) {
  31. reject(e);
  32. }
  33. }, 0);
  34. });
  35. this.onRejectedCallbacks.push(() => {
  36. setTimeout(() => {
  37. try {
  38. const x = onRejected(this.reason);
  39. resolvePromise(promise2, x, resolve, reject);
  40. } catch (e) {
  41. reject(e);
  42. }
  43. }, 0);
  44. });
  45. }
  46. });
  47. return promise2;
  48. }

1.3 解析Promise决议过程

resolvePromise函数处理thenable对象的解析,这是实现链式调用的关键:

  1. function resolvePromise(promise2, x, resolve, reject) {
  2. // 循环引用检查
  3. if (promise2 === x) {
  4. return reject(new TypeError('Chaining cycle detected for promise'));
  5. }
  6. // 防止多次调用
  7. let called = false;
  8. if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
  9. try {
  10. const then = x.then;
  11. if (typeof then === 'function') {
  12. then.call(
  13. x,
  14. y => {
  15. if (called) return;
  16. called = true;
  17. resolvePromise(promise2, y, resolve, reject);
  18. },
  19. r => {
  20. if (called) return;
  21. called = true;
  22. reject(r);
  23. }
  24. );
  25. } else {
  26. resolve(x);
  27. }
  28. } catch (e) {
  29. if (called) return;
  30. called = true;
  31. reject(e);
  32. }
  33. } else {
  34. resolve(x);
  35. }
  36. }

二、静态方法实现

2.1 Promise.all实现

all方法接收一个Promise可迭代对象,返回一个新Promise:

  • 所有输入Promise都成功时,返回按顺序包含结果的数组
  • 任意一个Promise失败时,立即返回失败的Promise
  1. static all(promises) {
  2. return new MyPromise((resolve, reject) => {
  3. const results = [];
  4. let completed = 0;
  5. const length = promises.length;
  6. if (length === 0) {
  7. resolve(results);
  8. return;
  9. }
  10. promises.forEach((promise, index) => {
  11. MyPromise.resolve(promise).then(
  12. value => {
  13. results[index] = value;
  14. completed++;
  15. if (completed === length) {
  16. resolve(results);
  17. }
  18. },
  19. reason => {
  20. reject(reason);
  21. }
  22. );
  23. });
  24. });
  25. }

2.2 Promise.race实现

race方法返回第一个决议的Promise(无论成功或失败):

  1. static race(promises) {
  2. return new MyPromise((resolve, reject) => {
  3. if (promises.length === 0) return;
  4. promises.forEach(promise => {
  5. MyPromise.resolve(promise).then(
  6. value => resolve(value),
  7. reason => reject(reason)
  8. );
  9. });
  10. });
  11. }

三、完整实现与测试

3.1 完整代码整合

将上述实现整合为完整类:

  1. class MyPromise {
  2. // ... 前文实现的constructor和then方法 ...
  3. static resolve(value) {
  4. if (value instanceof MyPromise) {
  5. return value;
  6. }
  7. return new MyPromise(resolve => resolve(value));
  8. }
  9. static reject(reason) {
  10. return new MyPromise((resolve, reject) => reject(reason));
  11. }
  12. static all(promises) {
  13. // ... 前文all实现 ...
  14. }
  15. static race(promises) {
  16. // ... 前文race实现 ...
  17. }
  18. catch(onRejected) {
  19. return this.then(null, onRejected);
  20. }
  21. finally(onFinally) {
  22. return this.then(
  23. value => MyPromise.resolve(onFinally()).then(() => value),
  24. reason => MyPromise.resolve(onFinally()).then(() => { throw reason; })
  25. );
  26. }
  27. }

3.2 测试用例示例

  1. // 测试all方法
  2. const promise1 = new MyPromise((resolve) => setTimeout(() => resolve(1), 100));
  3. const promise2 = new MyPromise((resolve) => setTimeout(() => resolve(2), 200));
  4. const promise3 = new MyPromise((resolve) => setTimeout(() => resolve(3), 300));
  5. MyPromise.all([promise1, promise2, promise3])
  6. .then(values => console.log(values)); // [1, 2, 3]
  7. // 测试race方法
  8. const fastPromise = new MyPromise(resolve => setTimeout(() => resolve('fast'), 100));
  9. const slowPromise = new MyPromise(resolve => setTimeout(() => resolve('slow'), 500));
  10. MyPromise.race([fastPromise, slowPromise])
  11. .then(value => console.log(value)); // 'fast'

四、实现要点总结

  1. 状态管理:必须确保状态只能从pending变为fulfilled或rejected,且不可逆
  2. 异步执行:使用setTimeout或微任务队列确保then回调异步执行
  3. 链式调用:通过返回新Promise实现then方法的链式调用
  4. 错误处理:在executor和then回调中都需要捕获异常
  5. 静态方法:all和race都需要处理空数组和异常情况

五、实际应用建议

  1. 调试技巧:在实现过程中添加console.log跟踪状态变化
  2. 边界测试:重点测试以下场景:
    • 空数组输入
    • 包含非Promise值的数组
    • 立即决议的Promise
    • 抛出异常的回调
  3. 性能优化:对于all方法,可以使用计数器优化完成判断
  4. 类型检查:添加参数类型检查增强鲁棒性

通过本文的手写实现,开发者可以深入理解Promise的工作原理,这不仅有助于解决实际开发中的问题,也为学习更高级的异步编程模式(如Async/Await)打下坚实基础。完整实现约200行代码,建议在实际项目中逐步扩展功能,如添加catch、finally等API。

相关文章推荐

发表评论