返回

Promise实现-完整版,满足MDN描述及Promise/A+规范

前端

Promise:让异步编程变得轻松

什么是 Promise?

Promise 是一种 JavaScript 对象,它代表了一个异步操作的最终完成或失败。它允许我们处理异步操作,就像它们是同步操作一样,从而简化代码并提高可读性。

Promise/A+ 规范

Promise/A+ 规范定义了 Promise 对象的行为标准。它确保不同浏览器和 JavaScript 环境中 Promise 的一致性。

Promise 实现原理

Promise 具有三个状态:

  • 待处理 (pending): 初始状态,表示操作尚未完成。
  • 已完成 (fulfilled): 操作已成功完成。
  • 已拒绝 (rejected): 操作失败。

当 Promise 构造函数执行时,它接受一个执行器函数,该函数包含两个回调:

  • resolve: 用于将 Promise 状态设置为 "fulfilled" 并提供一个值。
  • reject: 用于将 Promise 状态设置为 "rejected" 并提供一个错误。

执行器函数立即执行,并根据异步操作的结果调用 resolve 或 reject。

同步和异步内部函数

Promise 的内部函数可以是同步的或异步的:

  • 同步内部函数: 立即执行,并在 Promise 构造函数执行时调用。
  • 异步内部函数: 在以后执行,通常使用 setTimeoutXMLHttpRequest 等异步 API。

无论内部函数的类型如何,Promise 都会以相同的方式处理它们。

Promise 实现源代码

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

    executor(resolve, reject);
  }

  resolve(value) {
    if (this.state !== 'pending') return;

    this.state = 'fulfilled';
    this.value = value;
    this.onFulfilledCallbacks.forEach(callback => callback(value));
  }

  reject(reason) {
    if (this.state !== 'pending') return;

    this.state = 'rejected';
    this.reason = reason;
    this.onRejectedCallbacks.forEach(callback => callback(reason));
  }

  then(onFulfilled, onRejected) {
    // ...
  }

  catch(onRejected) {
    // ...
  }
}

then() 方法

then() 方法用于向 Promise 添加成功或失败回调。当 Promise 状态改变时,这些回调将被调用:

  • 如果 Promise 状态变为 "fulfilled",则调用成功回调并返回一个新 Promise。
  • 如果 Promise 状态变为 "rejected",则调用失败回调并返回一个新 Promise。

catch() 方法

catch() 方法是 then() 的快捷方式,用于处理错误。它只接受一个失败回调,并返回一个新 Promise。

常见问题解答

  1. Promise 的优点是什么?
    Promise 简化了异步编程,提高了代码的可读性。它允许我们串联异步操作,并避免回调地狱。

  2. Promise 如何处理错误?
    Promise 通过 reject() 回调处理错误,它将 Promise 的状态设置为 "rejected" 并提供一个错误。

  3. Promise 可以串联吗?
    是的,Promise 可以使用 then() 方法串联。每个 then() 返回一个新的 Promise,允许我们创建异步操作的链。

  4. Promise 与回调有什么区别?
    Promise 比回调更结构化和可管理。它允许我们顺序处理异步操作,而无需嵌套回调。

  5. 如何在浏览器中使用 Promise?
    所有现代浏览器都原生支持 Promise。您可以直接使用 Promise 构造函数创建 Promise 对象。