返回

用简单代码认识Promise的运行原理

前端

Promise的基本概念

Promise,通常被翻译成承诺或诺言,它是一种异步编程的解决方案。在 Promise 出现之前,通常的做法是使用回调函数,但随着JavaScript代码变得越来越复杂,回调函数很容易陷入“回调地狱”,使得代码难以维护。

Promise 的出现改变了这一切。它提供了一个统一的、基于状态的异步编程接口,使代码更易于理解和管理。

Promise的执行原理

为了更好地理解 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) {
    // 如果没有传递成功回调,则使用默认的处理函数
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
    // 如果没有传递失败回调,则使用默认的处理函数
    onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason };

    const promise = new Promise((resolve, reject) => {
      // 注册成功的回调函数
      this.onFulfilledCallbacks.push(() => {
        // 调用成功回调函数
        try {
          const result = onFulfilled(this.value);
          // 如果成功回调函数返回一个 Promise,则需要等待这个 Promise 完成
          if (result instanceof Promise) {
            result.then(resolve, reject);
          } else {
            // 如果成功回调函数返回一个普通值,则直接调用 resolve
            resolve(result);
          }
        } catch (error) {
          // 如果成功回调函数抛出错误,则直接调用 reject
          reject(error);
        }
      });

      // 注册失败的回调函数
      this.onRejectedCallbacks.push(() => {
        // 调用失败回调函数
        try {
          const result = onRejected(this.reason);
          // 如果失败回调函数返回一个 Promise,则需要等待这个 Promise 完成
          if (result instanceof Promise) {
            result.then(resolve, reject);
          } else {
            // 如果失败回调函数返回一个普通值,则直接调用 resolve
            resolve(result);
          }
        } catch (error) {
          // 如果失败回调函数抛出错误,则直接调用 reject
          reject(error);
        }
      });
    });

    return promise;
  }

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

Promise的使用示例

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("成功的值"); // 1秒后将 Promise 的状态变为成功
  }, 1000);
});

promise.then((value) => {
  console.log("成功回调函数执行,返回值:" + value);
}).catch((reason) => {
  console.log("失败回调函数执行,原因:" + reason);
});

在上面的示例中,我们创建了一个 Promise,并在 1 秒后将它的状态变为成功。然后,我们使用 then() 方法注册了成功的回调函数,并在回调函数中打印成功的值。同时,我们还注册了 catch() 方法,用于处理 Promise 失败的情况。

当这段代码执行时,它将在 1 秒后打印出"成功的值"。

总结

Promise 提供了一种更简单、更优雅的方式来处理异步编程。它使代码更易于理解和管理,并避免了陷入“回调地狱”。通过学习Promise 的基本概念和使用示例,您就可以在自己的项目中使用 Promise 来编写更优雅的异步代码。