自学内容网 自学内容网

JavaScript的Promise源码解析

在 JavaScript 中,Promise 是一种用于处理异步操作的对象,它提供了一种更优雅的方式来处理异步代码,避免了回调地狱的问题。下面是对 JS 的 Promise 源码的详细解析:

一、Promise 的基本结构

一个 Promise 对象主要包含以下几个部分:

  1. 状态:Promise 有三种状态,分别是 pending(等待中)、fulfilled(已成功)和 rejected(已失败)。初始状态为 pending,一旦状态确定就不可再改变。
  2. 值:当 Promise 状态变为 fulfilled 时,会有一个值与之对应;当状态变为 rejected 时,会有一个原因(reason)与之对应。
  3. 回调函数队列:分别用于存储当 Promise 状态变为 fulfilled 或 rejected 时要执行的回调函数。

以下是一个简单的 Promise 实现框架:

function Promise(executor) {
  const self = this;
  self.status = "pending";
  self.value = undefined;
  self.reason = undefined;
  self.onResolvedCallbacks = [];
  self.onRejectedCallbacks = [];

  function resolve(value) {
    if (self.status === "pending") {
      self.status = "fulfilled";
      self.value = value;
      self.onResolvedCallbacks.forEach((fn) => fn());
    }
  }

  function reject(reason) {
    if (self.status === "pending") {
      self.status = "rejected";
      self.reason = reason;
      self.onRejectedCallbacks.forEach((fn) => fn());
    }
  }

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

在这个框架中,executor 是一个函数,它在 Promise 被创建时立即执行。executor 接受两个参数,分别是 resolvereject 函数,用于在异步操作成功时调用 resolve 改变 Promise 的状态为 fulfilled,并传入结果值;在异步操作失败时调用 reject 改变 Promise 的状态为 rejected,并传入失败原因。

二、then 方法的实现

then 方法是 Promise 最重要的方法之一,它用于注册当 Promise 状态改变时要执行的回调函数,并返回一个新的 Promise 对象,以便实现链式调用。

Promise.prototype.then = function (onFulfilled, onRejected) {
  const self = this;
  let promise2;
  onFulfilled =
    typeof onFulfilled === "function" ? onFulfilled : (value) => value;
  onRejected =
    typeof onRejected === "function"
      ? onRejected
      : (reason) => {
          throw reason;
        };

  if (self.status === "fulfilled") {
    promise2 = new Promise((resolve, reject) => {
      try {
        const x = onFulfilled(self.value);
        resolvePromise(promise2, x, resolve, reject);
      } catch (e) {
        reject(e);
      }
    });
    return promise2;
  }

  if (self.status === "rejected") {
    promise2 = new Promise((resolve, reject) => {
      try {
        const x = onRejected(self.reason);
        resolvePromise(promise2, x, resolve, reject);
      } catch (e) {
        reject(e);
      }
    });
    return promise2;
  }

  if (self.status === "pending") {
    promise2 = new Promise((resolve, reject) => {
      self.onResolvedCallbacks.push(() => {
        try {
          const x = onFulfilled(self.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
      self.onRejectedCallbacks.push(() => {
        try {
          const x = onRejected(self.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    });
    return promise2;
  }
};

then 方法中,首先判断当前 Promise 的状态,如果是 fulfilled 或 rejected,则立即执行相应的回调函数,并通过 resolvePromise 函数处理回调函数的返回值,确保返回一个新的 Promise 对象。如果当前状态是 pending,则将回调函数存储在相应的队列中,等待状态改变时执行。

三、resolvePromise 函数的实现

resolvePromise 函数用于处理then方法中回调函数的返回值,确保 Promise 的链式调用正确工作。

function resolvePromise(promise2, x, resolve, reject) {
  let then;
  let thenCalledOrThrow = false;

  if (promise2 === x) {
    return reject(new TypeError("Chaining cycle detected for promise!"));
  }

  if (x instanceof Promise) {
    if (x.status === "pending") {
      x.then(function (value) {
        resolvePromise(promise2, value, resolve, reject);
      }, reject);
    } else {
      x.then(resolve, reject);
    }
    return;
  }

  if (x !== null && (typeof x === "object" || typeof x === "function")) {
    try {
      then = x.then;
      if (typeof then === "function") {
        then.call(
          x,
          function (y) {
            if (thenCalledOrThrow) return;
            thenCalledOrThrow = true;
            return resolvePromise(promise2, y, resolve, reject);
          },
          function (r) {
            if (thenCalledOrThrow) return;
            thenCalledOrThrow = true;
            return reject(r);
          }
        );
      } else {
        resolve(x);
      }
    } catch (e) {
      if (thenCalledOrThrow) return;
      thenCalledOrThrow = true;
      return reject(e);
    }
  } else {
    resolve(x);
  }
}

这个函数主要处理了以下几种情况:

  1. 如果返回值是自身,则抛出类型错误,因为不允许出现循环引用。
  2. 如果返回值是另一个 Promise,则根据其状态进行处理。
  3. 如果返回值是一个对象或函数,则尝试调用其then方法,如果存在的话。如果没有 then 方法,则直接将其值作为新 Promise 的结果。

四、catch 方法的实现

catch方法用于注册当 Promise 被拒绝时要执行的回调函数。

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

它实际上是调用 then 方法,并只传递拒绝回调函数。

通过以上的源码解析,可以深入理解 Promise 的工作原理和内部实现机制,这有助于更好地使用 Promise 来处理异步操作,并在需要时进行自定义的 Promise 扩展或优化。


原文地址:https://blog.csdn.net/yiguoxiaohai/article/details/142450831

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!