JavaScript中手写Promise

41 阅读2分钟

JavaScript中手写Promise

手写一个简单的 Promise 可以帮助深入理解其工作原理。以下是 Promise 的核心功能实现:

1. Promise 的基本结构

  • 状态

    • pending(进行中)

    • fulfilled(已成功)

    • rejected(已失败)

  • 方法

    • then:处理成功和失败的结果。

    • catch:处理失败的结果。

    • resolvereject:改变状态并触发回调。

2. 手写 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(fn => fn());
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };

    try {
      executor(resolve, reject); // 执行 executor
    } 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);
      } else if (this.state === 'rejected') {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      } else 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);
  }
}

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

3. 使用示例

const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => resolve('Success'), 1000);
});

promise
  .then(result => {
    console.log(result); // 输出: Success
    return 'Next Step';
  })
  .then(result => {
    console.log(result); // 输出: Next Step
  })
  .catch(error => {
    console.error(error);
  });

4. 功能说明

  • 状态管理

    • pendingfulfilledrejected 三种状态。
  • 回调队列

    • 使用数组存储成功和失败的回调函数。
  • 异步处理

    • 使用 setTimeout 模拟异步执行。
  • 链式调用

    • then 方法返回一个新的 Promise,支持链式调用。
  • 错误处理

    • 使用 catch 方法捕获错误。

总结

手写 Promise 的核心在于状态管理、回调队列和链式调用。通过实现这些功能,可以更好地理解 Promise 的工作原理。

更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github