Promise 的实例方法和静态方法有哪些,如何手动实现?

导读:Promise 是异步编程的一种解决方案,比传统的回调函数或事件更合理和更灵活。本文主要展示 Promise 提供的方法列表,以及基本的实现原理。通过本文,我们能加深 Promise 方法的理解和场景使用,对 Promise.all、Promise.race、Promise.allSettled 和 Promise.any 四个方法的异同之处也有更深层次的领悟。

一、Promise 方法列表

Promise 的实例方法有 then/catch/finally 三种,静态方法有 all/race/allSettled/any/resolve/reject 六种。其中 then 实现起来因为涉及 Promise 裁决过程(The Promise Resolution Procedure),会比较复杂,其余的都是基于已有功能的拓展。下面都给大伙列出所有的方法。

  1. Promise.prototype.then()
  2. Promise.prototype.catch()
  3. Promise.prototype.finally()
  4. Promise.all()
  5. Promise.race)
  6. Promise.allSettled)
  7. Promise.any()
  8. Promise.resolve()
  9. Promise.reject()

二、Promise 九种方法实现

1. 原型方法 then

then 方法是整个 Promise 解决的核心内容,同时因为回调函数和返回一个新的 Promise 实例,因此决议过程比较复杂。这里也是直接说明 then 方法的定义,具体可以看一篇文章手写一个 Promises/A+和理解核心概念

// class MyPromise {
//     static PENDING = 'pending'; // 进行中
//     static FULFILLED = 'fulfilled'; // 已成功
//     static REJECTED = 'rejected'; // 已失败
//     state = MyPromise.PENDING;
//     value = null;
//     reason = null;
//     onFulfilledCallbacks = [];
//     onRejectedCallbacks = [];
//     ...
// }
MyPromise.prototype.then = (onFulfilled, onRejected) => {
  if (typeof onFulfilled != 'function') {
    onFulfilled = (value) => value;
  }
  if (typeof onRejected != 'function') {
    onRejected = (reason) => {
      throw reason;
    };
  }
  // Promise 核心解决过程 见规范2.3
  const _resolvePromise = (promise, x, resolve, reject) => {
    // 2.3.1 如果 promise 和 x 指向同一对象,抛出 TypeError 错误
    if (promise === x) {
      const errMsg = 'The promise and the return value are the same';
      return reject(new TypeError(errMsg));
    }

    // 2.3.3 如果 x 为对象(不是null)或者函数
    if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
      let then = null;
      try {
        // 2.3.3.1. 检索属性 x.then
        then = x.then;
      } catch (error) {
        // 2.3.3.2 如果 x.then 导致抛出异常 e,则以 e 为拒绝原因拒绝 promis
        return reject(error);
      }

      // 2.3.3.3 如果 then 是一个函数,x 作为 then 的 this 调用该方法,第一个参数是成功的回调函数,第二个参数是失败的回调函数
      if (typeof then === 'function') {
        let called = false;
        try {
          then.call(
            x,
            (y) => {
              // 2.3.3.3.4 如果成功回调与失败回调都被调用或多次调用同一个参数,则第一个调用优先,其他调用都将被忽略。
              if (called) return;
              called = true;
              // 2.3.3.3.1 如果成功回调以值 y 调用,运行 [[Resolve]](promise,y)
              _resolvePromise(promise, y, resolve, reject);
            },
            (r) => {
              // 2.3.3.3.4 如果成功回调与失败回调都被调用或多次调用同一个参数,则第一个调用优先,其他调用都将被忽略。
              if (called) return;
              called = true;
              // 2.3.3.3.2 如果失败回调以原因 r 调用,用 r 拒绝 promise
              reject(r);
            }
          );
        } catch (error) {
          // 2.3.3.4 如果调用 then 方法抛出异常 e:
          // 2.3.3.4.1 若成功回调或失败回调都调用过,忽略
          if (called) return;

          // 2.3.3.4.2 未调用,用 e 作为原因拒绝 promise
          reject(error);
        }
      } else {
        // 2.3.3.4. 如果 then 不是函数,用 x 作为值完成 promise
        return resolve(x);
      }
    } else {
      // 2.3.4 如果 x 不为对象或者函数,以 x 为参数执行 promise
      return resolve(x);
    }
  };
  // 链式返回的Promise
  const newPromise = new MyPromise((resolve, reject) => {
    switch (this.state) {
      case MyPromise.FULFILLED:
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            _resolvePromise(newPromise, x, resolve, reject);
          } catch (reason) {
            reject(reason);
          }
        }, 0);
        break;
      case MyPromise.REJECTED:
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            _resolvePromise(newPromise, x, resolve, reject);
          } catch (reason) {
            reject(reason);
          }
        }, 0);
        break;
      case MyPromise.PENDING:
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              _resolvePromise(newPromise, x, resolve, reject);
            } catch (reason) {
              reject(reason);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              _resolvePromise(newPromise, x, resolve, reject);
            } catch (reason) {
              reject(reason);
            }
          }, 0);
        });
        break;
    }
  });
  return newPromise;
}; 

2. 原型方法 catch

如果上面没有定义 reject 方法或者在抛出错误,那么所有的异常会走向 catch 方法,而 catch 可以复用 then 方法。

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

3. 原型方法 finally

不管是 resolve 还是 reject 都会调用 finally 。那么相当于 fianlly 方法替使用者分别调用了一次 then 的 resolved 和 rejected 状态回调。

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

4. 静态方法 Promise.all

Promise.all() 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。所有参数数组 Promise 实例执行 resolve 回调后,新实例执行 resolve 回调;如果中间有任何一个 Promise 实例执行 reject 回调,那么新实例就直接执行 reject 回调了。

打个比方:多名员工分别同时进行多个项目,你要求任何一个项目都必须是令你满意的,有一个不满意都算这件事(所有项目)是失败的。强调的是整体令你满意。

MyPromise.all = function (promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      resolve([]);
    } else {
      let result = [];
      let index = 0;
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (data) => {
            result[i] = data;
            if (++index === promises.length) {
              resolve(result);
            }
          },
          (err) => {
            reject(err);
            return;
          }
        );
      }
    }
  });
}; 

5. 静态方法 Promise.race

Promise.race() 顾名思义,就是竞赛,返回最快完成那一个 Promise 实例。只要参数数组中有一个 Promise 实例执行 resolve 回调或 reject 回调后,新实例就直接返回结果。

打个比方:多名员工分别同时进行多个项目,你只要最快完成的项目,无论项目是否令你满意。强调的是要快。

MyPromise.race = function (promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      resolve();
    } else {
      let index = 0;
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (data) => {
            resolve(data);
          },
          (err) => {
            reject(err);
            return;
          }
        );
      }
    }
  });
}; 

6. 静态方法 Promise.allSettled

Promise.allSettled() 方法只有等到参数数组的所有 Promise 实例都发生状态变更,返回的 Promise 实例才会发生状态变更,无论是执行 resolve 回调还是 reject 回调的状态。

打个比方:多名员工分别同时进行多个项目,你要求每个一个项目都必须完成,然后得到所有项目是令你满意还是令你不满意的。强调的是最终结果。

MyPromise.allSettled = function (promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      resolve([]);
    } else {
      let result = [];
      let index = 0;
      for (let i = 0; i < promises.length; i++) {
        promises[i]
          .then(
            (value) => {
              result[i] = {
                status: 'fulfilled',
                value,
              };
            },
            (reason) => {
              result[i] = {
                status: 'rejected',
                reason,
              };
            }
          )
          .finally(() => {
            if (++index === promises.length) {
              return resolve(result);
            }
          });
      }
    }
  });
}; 

同时因为 Promise.allSettled()Promise.all() 都是对所有 Promise 实例的一种处理,下面就可以利用 Promise.all() 来实现 Promise.allSettled() 方法。

MyPromise.allSettled = function (promises) {
  return Promise.all(
    promises.map((item) =>
      Promise.resolve(item).then(
        (value) => ({ status: 'fulfilled', value }),
        (reason) => ({ status: 'rejected', reason })
      )
    )
  );
}; 

7. 静态方法 Promise.any

Promise.any() 方法是返回任意一个最快执行 resolve 回调的 Promise 实例。

打个比方:多名员工同时进行多个项目,你只要最快得到令你满意的那个项目,无论所有项目最终都没令你满意,这件事(所有项目)才算是失败了。强调的是又快又好。

MyPromise.any = function (promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      return resolve();
    } else {
      let result = [];
      let index = 0;
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (value) => {
            return resolve(value);
          },
          (reason) => {
            result[i] = reason;
            if (++index === promises.length) {
              return reject(new AggregateError(result));
            }
          }
        );
      }
    }
  });
}; 

8. 静态方法 Promise.resolve

Promise.resolve 方法返回一个以给定值解析后的 Promise 实例。相当于执行 then 方法里面的 _resolvePromise

MyPromise.reject = function (value) {
  return new MyPromise((resolve, reject) => {
    resolve(value);
  });
}; 

9. 静态方法 Promise.reject

Promise.reject 方法返回一个带有拒绝原因的 Promise 实例。

MyPromise.reject = function (reason) {
  return new MyPromise((resolve, reject) => {
    reject(reason);
  });
}; 
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 Promise 的所有方法和一个实例的代码示例: 1. Promise 构造函数: ```javascript const myPromise = new Promise((resolve, reject) => { // 异步操作 }); ``` 2. Promise.prototype.then(): ```javascript myPromise.then((result) => { // 异步操作成功的处理逻辑 }).catch((error) => { // 异步操作失败的处理逻辑 }); ``` 3. Promise.prototype.catch(): ```javascript myPromise.catch((error) => { // 异步操作失败的处理逻辑 }); ``` 4. Promise.all(): ```javascript const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('操作1成功'); }, 1000); }); const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('操作2成功'); }, 2000); }); Promise.all([promise1, promise2]) .then((results) => { console.log('所有操作成功:', results); }) .catch((error) => { console.log('操作失败:', error); }); ``` 5. Promise.race(): ```javascript const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('操作1成功'); }, 1000); }); const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('操作2成功'); }, 2000); }); Promise.race([promise1, promise2]) .then((result) => { console.log('最先完成的操作成功:', result); }) .catch((error) => { console.log('操作失败:', error); }); ``` 6. Promise.resolve(): ```javascript const value = '操作成功'; Promise.resolve(value) .then((result) => { console.log('操作成功:', result); }) .catch((error) => { console.log('操作失败:', error); }); ``` 7. Promise.reject(): ```javascript const error = '操作失败'; Promise.reject(error) .then((result) => { console.log('操作成功:', result); }) .catch((error) => { console.log('操作失败:', error); }); ``` 这些是 Promise 的常用方法和一个简单的实例代码。根据具体需求,可以灵活运用这些方法进行异步操作的处理。 如果您有更多问题,请随时追问!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值