返回

从使用层面手写Promise源码解析及使用规则

前端

Promise:深入解析其实现与使用

Promise,JavaScript 中的异步利器

在 JavaScript 开发中,我们经常需要处理异步操作。Promise 作为一种优雅高效的机制,正是为应对这一挑战而生。它能够帮助我们轻松管理异步任务,并通过一系列方法和规则确保代码的清晰性和可维护性。

Promise 源码实现

要深入理解 Promise,我们可以从其源码实现入手:

class Promise {
  constructor(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));
    };

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

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

  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

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

  static resolve(value) {
    return new Promise((resolve) => resolve(value));
  }

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

  static all(promises) {
    return new Promise((resolve, reject) => {
      let results = [];
      let completedCount = 0;
      promises.forEach((promise, index) => {
        promise
          .then((value) => {
            results[index] = value;
            completedCount++;
            if (completedCount === promises.length) {
              resolve(results);
            }
          })
          .catch((reason) => reject(reason));
      });
    });
  }

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

Promise 使用规则

在使用 Promise 时,需要遵循一些基本规则:

  • Promise 是一个对象,可通过 new 创建。
  • 构造函数接受一个 executor 函数,该函数有两个参数:resolve 和 reject。
  • resolve 函数用于将 Promise 状态更改为 "fulfilled",并传递成功值。
  • reject 函数用于将 Promise 状态更改为 "rejected",并传递失败原因。
  • then 方法用于在 Promise 状态改变时执行回调函数。
  • catch 方法用于在 Promise 状态变为 "rejected" 时执行回调函数。
  • finally 方法用于无论 Promise 状态如何都执行回调函数。
  • Promise.resolve 方法用于创建一个立即成功解析的新 Promise。
  • Promise.reject 方法用于创建一个立即失败解析的新 Promise。
  • Promise.all 方法用于等待一组 Promise 全部完成,然后以成功状态解析,如果其中一个 Promise 失败,则以失败状态解析。
  • Promise.race 方法用于等待一组 Promise 中率先完成的 Promise,然后以成功状态解析,如果其中一个 Promise 失败,则以失败状态解析。

Promise 的优势

使用 Promise 具有以下优势:

  • 简化异步代码: Promise 可以将复杂的异步操作转换为更易读、易维护的同步代码。
  • 可串联调用: Promise 的 then 方法允许以可读的方式串联调用异步操作。
  • 错误处理: Promise 的 catch 方法提供了一种统一的方式来处理异步操作中的错误。
  • 状态管理: Promise 提供了明确的状态管理,可以轻松跟踪异步操作的进度。

常见问题解答

  1. Promise 的状态有哪些?

    • pending
    • fulfilled
    • rejected
  2. 如何处理 Promise 的错误?

    • 使用 catch 方法
  3. 如何等待多个 Promise 完成?

    • 使用 Promise.all 方法
  4. 如何获取率先完成的 Promise?

    • 使用 Promise.race 方法
  5. Promise 的 finally 方法的作用是什么?

    • 无论 Promise 状态如何,都会执行指定的操作