返回

Promise 从入门到手写 | [Promise系列一]

前端

前言

在现代前端开发中,异步编程已经成为常态。各种异步操作,如网络请求、定时器、文件操作等,都需要我们妥善处理。传统的回调函数的方式虽然可以实现异步编程,但随着异步操作的增多,代码很容易变得混乱和难以维护。

Promise 是一种更优雅、更强大的异步编程方式。它可以帮助我们更好地管理和组织异步操作,让代码更加清晰和易于阅读。

Promise 介绍

Promise 是一个 JavaScript 对象,它代表一个异步操作的最终结果。Promise 有三种状态:

  • Pending: 初始状态,表示异步操作尚未完成。
  • Fulfilled: 成功状态,表示异步操作已完成并成功返回结果。
  • Rejected: 失败状态,表示异步操作已完成但发生错误。

Promise 特点

Promise 有以下几个特点:

  • 可链式调用: Promise 支持链式调用,即一个 Promise 可以接着另一个 Promise 执行。这使得我们可以很方便地处理多个异步操作的组合。
  • 状态不可变: Promise 的状态一旦确定,就不可更改。这意味着 Promise 的状态只会从 Pending 变为 Fulfilled 或 Rejected,不会再发生其他变化。
  • 可以取消: Promise 可以被取消,即在异步操作完成之前,我们可以调用 Promise 的 cancel() 方法来取消该操作。
  • 可以处理错误: Promise 可以捕获和处理异步操作中发生的错误。这使得我们可以更方便地处理错误情况。

Promise 使用

Promise 的使用非常简单。我们首先需要创建一个 Promise 对象,然后调用 then() 方法来注册回调函数。then() 方法有两个参数,第一个参数是成功回调函数,第二个参数是失败回调函数。

当 Promise 的状态变为 Fulfilled 时,会调用成功回调函数。当 Promise 的状态变为 Rejected 时,会调用失败回调函数。

Promise 手写实现

我们可以自己手写一个 Promise 对象。虽然手写 Promise 对象比较复杂,但它可以帮助我们更好地理解 Promise 的原理。

class Promise {
  constructor(executor) {
    this.state = "pending";
    this.result = undefined;
    this.successCallbacks = [];
    this.failureCallbacks = [];

    // 立即执行 executor 函数
    executor(this.resolve.bind(this), this.reject.bind(this));
  }

  resolve(result) {
    if (this.state !== "pending") {
      return;
    }

    this.state = "fulfilled";
    this.result = result;

    // 执行所有成功回调函数
    this.successCallbacks.forEach((callback) => {
      callback(this.result);
    });
  }

  reject(error) {
    if (this.state !== "pending") {
      return;
    }

    this.state = "rejected";
    this.result = error;

    // 执行所有失败回调函数
    this.failureCallbacks.forEach((callback) => {
      callback(this.result);
    });
  }

  then(successCallback, failureCallback) {
    // 如果成功回调函数不存在,则返回一个新的 Promise 对象,该对象的状态为 Fulfilled,结果为 undefined
    if (!successCallback) {
      return new Promise((resolve) => {
        resolve(undefined);
      });
    }

    // 如果失败回调函数不存在,则返回一个新的 Promise 对象,该对象的状态为 Rejected,结果为 error
    if (!failureCallback) {
      return new Promise((_, reject) => {
        reject(this.result);
      });
    }

    // 将成功回调函数和失败回调函数添加到回调函数数组中
    this.successCallbacks.push(successCallback);
    this.failureCallbacks.push(failureCallback);

    // 如果 Promise 的状态已经确定,则立即执行回调函数
    if (this.state !== "pending") {
      this.state === "fulfilled"
        ? successCallback(this.result)
        : failureCallback(this.result);
    }

    return this;
  }

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

  finally(callback) {
    return this.then(
      (result) => {
        callback();
        return result;
      },
      (error) => {
        callback();
        throw error;
      }
    );
  }
}

总结

Promise 是一种非常强大的异步编程工具。它可以帮助我们更好地管理和组织异步操作,让代码更加清晰和易于阅读。在现代前端开发中,Promise 已经成为一种必备的技能。