返回

手把手教你实现Promise,加深对Promise的认识

前端

Promise是JavaScript中用于异步编程的强大工具,它可以帮助我们处理异步操作并实现代码的可读性和可维护性。在本文中,我们将从头开始手写一个Promise,并逐步讲解它的核心原理。通过这个过程,你将对Promise有更深刻的理解,并能够将其应用到自己的项目中。

Promise的状态

Promise有三种状态:pending、fulfilled和rejected。Pending状态表示Promise尚未完成,fulfilled状态表示Promise已经成功完成,rejected状态表示Promise已经失败。

Promise的构造函数

Promise的构造函数接收一个executor函数作为参数,executor函数有两个参数:resolve和reject。resolve用于将Promise的状态从pending变为fulfilled,reject用于将Promise的状态从pending变为rejected。

function Promise(executor) {
  this.state = 'pending';
  this.value = undefined;
  this.reason = undefined;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  const resolve = (value) => {
    if (this.state !== 'pending') return;
    this.state = 'fulfilled';
    this.value = value;
    this.onFulfilledCallbacks.forEach((callback) => callback(value));
  };

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

  executor(resolve, reject);
}

Promise的then方法

Promise的then方法用于添加回调函数来处理Promise的结果。then方法接收两个参数:onFulfilled和onRejected。onFulfilled用于处理Promise成功完成的结果,onRejected用于处理Promise失败的原因。

Promise.prototype.then = function(onFulfilled, onRejected) {
  if (this.state === 'fulfilled') {
    onFulfilled(this.value);
  } else if (this.state === 'rejected') {
    onRejected(this.reason);
  } else {
    this.onFulfilledCallbacks.push(onFulfilled);
    this.onRejectedCallbacks.push(onRejected);
  }

  return new Promise((resolve, reject) => {
    if (this.state === 'fulfilled') {
      resolve(onFulfilled(this.value));
    } else if (this.state === 'rejected') {
      reject(onRejected(this.reason));
    } else {
      this.onFulfilledCallbacks.push(() => {
        resolve(onFulfilled(this.value));
      });
      this.onRejectedCallbacks.push(() => {
        reject(onRejected(this.reason));
      });
    }
  });
};

Promise的catch方法

Promise的catch方法用于处理Promise失败的原因。catch方法接收一个参数:onRejected。onRejected用于处理Promise失败的原因。

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

Promise的finally方法

Promise的finally方法用于无论Promise成功还是失败都会执行的回调函数。finally方法接收一个参数:onFinally。onFinally用于无论Promise成功还是失败都会执行的回调函数。

Promise.prototype.finally = function(onFinally) {
  return this.then(
    (value) => {
      onFinally();
      return value;
    },
    (reason) => {
      onFinally();
      throw reason;
    }
  );
};

完整代码

function Promise(executor) {
  this.state = 'pending';
  this.value = undefined;
  this.reason = undefined;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  const resolve = (value) => {
    if (this.state !== 'pending') return;
    this.state = 'fulfilled';
    this.value = value;
    this.onFulfilledCallbacks.forEach((callback) => callback(value));
  };

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

  executor(resolve, reject);
}

Promise.prototype.then = function(onFulfilled, onRejected) {
  if (this.state === 'fulfilled') {
    onFulfilled(this.value);
  } else if (this.state === 'rejected') {
    onRejected(this.reason);
  } else {
    this.onFulfilledCallbacks.push(onFulfilled);
    this.onRejectedCallbacks.push(onRejected);
  }

  return new Promise((resolve, reject) => {
    if (this.state === 'fulfilled') {
      resolve(onFulfilled(this.value));
    } else if (this.state === 'rejected') {
      reject(onRejected(this.reason));
    } else {
      this.onFulfilledCallbacks.push(() => {
        resolve(onFulfilled(this.value));
      });
      this.onRejectedCallbacks.push(() => {
        reject(onRejected(this.reason));
      });
    }
  });
};

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

Promise.prototype.finally = function(onFinally) {
  return this.then(
    (value) => {
      onFinally();
      return value;
    },
    (reason) => {
      onFinally();
      throw reason;
    }
  );
};

希望通过本文,你能够对Promise有更深刻的理解。如果你有任何问题或建议,欢迎在评论区留言。