【手写 Promise 】

27 篇文章 0 订阅
17 篇文章 0 订阅

了解Promise

Promise 是一种异步编程解决方案,它提供了一种更加优美和便捷的方式来处理异步操作。下面是手写 Promise 的详细步骤和分析。

首先,我们需要了解 Promise 的三种状态:

  • Pending(进行中)
  • Fulfilled(已成功)
  • Rejected(已失败)

当一个 Promise 被创建时,它的状态是 Pending。当 Promise 成功执行回调函数时,它的状态变成 Fulfilled。如果执行回调函数时发生了异常,Promise 的状态会变成 Rejected。

定义一个 Promise

接下来,我们需要定义一个 Promise 构造函数,它需要一个执行器函数作为参数。执行器函数接受两个参数 resolve 和 reject,它们是两个函数,用于修改 Promise 的状态。

class MyPromise {
  constructor(executor) {
    this.status = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.status === 'pending') {
        this.status = 'fulfilled';
        this.value = value;
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };

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

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

在构造函数中,我们定义了 Promise 的状态和值。onResolvedCallbacks 和 onRejectedCallbacks 数组用于存储 then 方法中传入的回调函数,当 Promise 的状态改变时,我们需要依次执行这些回调函数。

定义 then 方法

然后,我们需要定义 then 方法,它接受两个参数 onFulfilled 和 onRejected,它们分别是 Promise 成功和失败时的回调函数。

class MyPromise {
  // ...

  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.status === 'fulfilled') {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      } else if (this.status === 'rejected') {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      } else if (this.status === 'pending') {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
      }
    });

    return promise2;
  }
}

判断 Promise 的状态

在 then 方法中,我们首先需要判断 Promise 的状态。如果状态为 Fulfilled,直接调用 onFulfilled 回调函数,并且将返回值传入 resolvePromise 函数。resolvePromise 函数用于处理返回值,如果返回值为 Promise,则等待其状态改变后再传递结果。

如果状态为 Rejected,直接调用 onRejected 回调函数,并且将返回值传入 resolvePromise 函数。

如果状态为 Pending,将回调函数 push 到回调队列中。当 Promise 的状态改变时,依次执行这些回调函数,并在执行完成后,再调用 resolvePromise 函数。

在 resolvePromise 函数中,我们需要判断返回值的类型。如果为 Promise,则等待其状态改变后再传递结果。

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

  let called = false;

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

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

在 resolvePromise 函数中,我们首先需要判断 x 和 promise2 是否相等,如果相等,说明出现了循环引用,需要抛出错误。

然后,我们需要判断 x 的类型。如果 x 是对象或函数,我们需要判断它是否有 then 方法。如果有 then 方法,则说明 x 是 Promise,需要等待其状态改变后再传递结果。否则,直接将 x 传递给 resolve 函数。

定义 static 方法 resolve 和 reject

最后,我们需要在 Promise 类中定义 static 方法 resolve 和 reject,用于创建已经成功和失败的 Promise。

class MyPromise {
  // ...

  static resolve(value) {
    if (value instanceof MyPromise) {
      return value;
    }

    return new MyPromise((resolve) => resolve(value));
  }

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

最终,我们得到了手写的 Promise 实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值