返回

**从零开始,用 JavaScript 手写 Promise,彻底掌握异步编程

前端

理解 JavaScript Promise:深入浅出的指南

简介

异步编程在 JavaScript 中无处不在,但它常常给开发者带来挑战。在传统上,回调函数被用来处理异步操作,但它们容易导致代码杂乱和难以维护。

Promise 的曙光

Promise 是一种新的技术,出现在 ES6 规范中,旨在优雅而健壮地处理异步操作。它提供了一种清晰简洁的方式来表示异步操作的状态和结果。

Promise 的本质

一个 Promise 可以处于三种状态之一:

  • 待定(Pending) :初始状态,表示操作正在进行。
  • 已完成(Resolved) :操作成功完成,带有结果值。
  • 已拒绝(Rejected) :操作失败,带有错误值。

创建 Promise

创建 Promise 的过程非常简单:

const promise = new Promise((resolve, reject) => {
  // 异步操作
  if (condition) {
    resolve(result);
  } else {
    reject(error);
  }
});

其中:

  • resolve 函数用于设置 Promise 为 已完成 状态,并传递结果值。
  • reject 函数用于设置 Promise 为 已拒绝 状态,并传递错误值。

使用 Promise

一旦创建了 Promise,我们就可以使用 .then().catch() 方法来处理它的结果:

promise
  .then((result) => {
    // 处理成功结果
  })
  .catch((error) => {
    // 处理失败结果
  });

示例:模拟异步网络请求

为了更好地理解 Promise,让我们编写一个简单的示例,模拟一个异步的网络请求:

function fetchUserData(userId) {
  return new Promise((resolve, reject) => {
    // 模拟异步网络请求
    setTimeout(() => {
      if (userId === 1) {
        resolve({ name: 'John', age: 30 });
      } else {
        reject(new Error('User not found'));
      }
    }, 1000);
  });
}

fetchUserData(1)
  .then((data) => {
    console.log(`User found: ${data.name}`);
  })
  .catch((error) => {
    console.error(`Error: ${error.message}`);
  });

Promise 的优点

使用 Promise 进行异步编程具有诸多优势:

  • 可读性和可维护性 :Promise 消除了回调函数的嵌套,使代码更易于阅读和维护。
  • 错误处理 :Promise 提供了统一的错误处理机制, упрощая捕获和处理异步操作中的错误。
  • 组合性 :Promise 可以很容易地组合在一起,使我们能够轻松地创建复杂的异步操作序列。

手写 Promise 实现

自己手写 Promise 实现是一个极好的练习,可以加深我们对 Promise 底层工作原理的理解。我们可以按照以下步骤操作:

1. 创建 Promise 类

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

    // 立即执行 executor 函数,传递 resolve 和 reject 函数
    try {
      executor(this.resolve.bind(this), this.reject.bind(this));
    } catch (error) {
      this.reject(error);
    }
  }

  // 将 Promise 设置为已完成,并调用 onFulfilled 回调
  resolve(value) {
    if (this.state !== 'pending') return;

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

  // 将 Promise 设置为已拒绝,并调用 onRejected 回调
  reject(error) {
    if (this.state !== 'pending') return;

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

  // 添加 onFulfilled 回调
  then(onFulfilled) {
    if (this.state === 'pending') {
      this.onFulfilledCallbacks.push(onFulfilled);
    } else if (this.state === 'fulfilled') {
      onFulfilled(this.result);
    }

    return this;
  }

  // 添加 onRejected 回调
  catch(onRejected) {
    if (this.state === 'pending') {
      this.onRejectedCallbacks.push(onRejected);
    } else if (this.state === 'rejected') {
      onRejected(this.result);
    }

    return this;
  }
}

2. 使用 Promise 类

const promise = new Promise((resolve, reject) => {
  // 异步操作
  if (condition) {
    resolve(result);
  } else {
    reject(error);
  }
});

promise
  .then((result) => {
    // 处理成功结果
  })
  .catch((error) => {
    // 处理失败结果
  });

常见问题解答

1. 什么是 Promise?

Promise 是一种 JavaScript 技术,用于异步编程,提供了一种简洁优雅的方式来处理异步操作的状态和结果。

2. Promise 有哪些优点?

Promise 具有可读性、可维护性、更好的错误处理和可组合性等优点。

3. 如何创建 Promise?

通过调用 new Promise() 构造函数并传递一个执行器函数,执行器函数接收 resolvereject 函数,用于设置 Promise 的状态和结果。

4. 如何使用 Promise?

可以使用 .then().catch() 方法来处理 Promise 的结果,.then() 用于处理成功结果,.catch() 用于处理失败结果。

5. 什么是 Promise 的状态?

Promise 可以处于三种状态之一:待定(Pending)、已完成(Resolved)或已拒绝(Rejected)。

结论

掌握 Promise 是 JavaScript 异步编程的必备技能。通过理解其工作原理,我们可以编写出更加清晰、健壮的异步代码。从手写 Promise 实现到实际应用,本文逐步引导读者深入了解 Promise 的方方面面,使其成为异步编程的利器。