返回

Promise再难也不怕!带你一次学会Promise及A+规范!

前端

Promise是一种用来处理异步编程的工具。它是一种对象,表示一个异步操作的最终完成或失败。Promise可以用来解决回调函数的嵌套问题,使异步编程更加容易和可读。

PromiseA+规范是JavaScript Promise的一个实现规范。它定义了Promise的行为,以便不同的JavaScript实现可以兼容。PromiseA+规范包括以下主要内容:

  • Promise有三种状态:pending(等待)、fulfilled(已完成)和rejected(已拒绝)。
  • Promise的then()方法用于添加回调函数,以处理Promise的状态变化。
  • Promise的catch()方法用于处理Promise的拒绝。
  • Promise的all()方法用于等待多个Promise同时完成。
  • Promise的race()方法用于等待多个Promise中第一个完成的Promise。

现在,我们来实现一个简化版的Promise。该Promise将遵循PromiseA+规范,但功能将比标准Promise更简单。

function Promise(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((callback) => {
        callback(value);
      });
    }
  };

  const reject = (reason) => {
    if (this.state === 'pending') {
      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) => {
    this.then((value) => {
      try {
        const result = onFulfilled(value);
        resolve(result);
      } catch (error) {
        reject(error);
      }
    }, (reason) => {
      try {
        const result = onRejected(reason);
        resolve(result);
      } catch (error) {
        reject(error);
      }
    });
  });
};

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

Promise.all = function (promises) {
  return new Promise((resolve, reject) => {
    const values = [];
    let count = 0;

    promises.forEach((promise, index) => {
      promise.then((value) => {
        values[index] = value;
        count++;

        if (count === promises.length) {
          resolve(values);
        }
      }, (reason) => {
        reject(reason);
      });
    });
  });
};

Promise.race = function (promises) {
  return new Promise((resolve, reject) => {
    promises.forEach((promise) => {
      promise.then((value) => {
        resolve(value);
      }, (reason) => {
        reject(reason);