返回

Promise:你所必知的知识点

前端

概述:

在过去的岁月里,人们一直为编写高效、易于维护的JavaScript异步代码而苦苦挣扎。在很长一段时间里,回调函数是异步编程的标准工具,但它带来了难以处理的嵌套回调地狱,维护起来非常困难。

Promise的出现彻底改变了这一局面。它通过提供一种更直观、更易于理解的方式来编写异步代码,使得异步编程变得更加容易。Promise允许你在异步代码中以同步的方式编写代码,从而消除嵌套回调地狱的困扰,并显著提高代码的可读性和可维护性。

Promise的基本使用:

Promise的基本用法非常简单。首先,你需要创建一个Promise对象,然后将一个函数作为参数传递给它的构造函数。这个函数被称为Promise的executor函数。

const promise = new Promise((resolve, reject) => {
  // 在executor函数中编写异步代码
});

在executor函数中,你可以编写异步代码。当异步操作完成后,你需要调用resolve函数来表示操作成功,或者调用reject函数来表示操作失败。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("操作成功!");
  }, 2000);
});

一旦Promise对象被创建,你可以使用.then()方法来处理它的结果。.then()方法接受两个参数:一个用于处理成功结果的函数,一个用于处理失败结果的函数。

promise.then((result) => {
  console.log(result); // "操作成功!"
}, (error) => {
  console.error(error);
});

手写Promise的实现:

为了更好地理解Promise的工作原理,你可以尝试自己手写一个简单的Promise实现。以下是如何手写Promise的示例:

class Promise {
  constructor(executor) {
    this.state = "pending"; // 初始状态为pending
    this.result = undefined; // 结果尚未确定
    this.successCallbacks = []; // 存储成功回调函数的数组
    this.failureCallbacks = []; // 存储失败回调函数的数组

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

  // resolve函数用于标记Promise为成功状态并存储结果
  resolve(result) {
    if (this.state !== "pending") return;

    this.state = "fulfilled"; // 将状态更改为fulfilled
    this.result = result; // 存储结果

    // 调用所有成功回调函数
    for (const callback of this.successCallbacks) {
      callback(result);
    }
  }

  // reject函数用于标记Promise为失败状态并存储错误原因
  reject(error) {
    if (this.state !== "pending") return;

    this.state = "rejected"; // 将状态更改为rejected
    this.result = error; // 存储错误原因

    // 调用所有失败回调函数
    for (const callback of this.failureCallbacks) {
      callback(error);
    }
  }

  // then方法用于添加成功回调函数和失败回调函数
  then(successCallback, failureCallback) {
    // 如果Promise已成功,则立即调用成功回调函数
    if (this.state === "fulfilled") {
      successCallback(this.result);
      return this;
    }

    // 如果Promise已失败,则立即调用失败回调函数
    if (this.state === "rejected") {
      failureCallback(this.result);
      return this;
    }

    // 如果Promise尚未完成,则将成功回调函数和失败回调函数存储起来,以便在Promise完成时调用它们
    this.successCallbacks.push(successCallback);
    this.failureCallbacks.push(failureCallback);

    return this;
  }
}

面试题解析:

1. 解释Promise的基本原理。

Promise是一种用于处理异步编程的工具。它允许你在异步代码中以同步的方式编写代码,从而消除嵌套回调地狱的困扰,并显著提高代码的可读性和可维护性。

2. Promise的状态有哪些?

Promise有三种状态:pending、fulfilled和rejected。pending表示Promise尚未完成,fulfilled表示Promise已成功完成,rejected表示Promise已失败完成。

3. 如何使用Promise?

首先,你需要创建一个Promise对象,然后将一个函数作为参数传递给它的构造函数。这个函数被称为Promise的executor函数。在executor函数中,你可以编写异步代码。当异步操作完成后,你需要调用resolve函数来表示操作成功,或者调用reject函数来表示操作失败。

一旦Promise对象被创建,你可以使用.then()方法来处理它的结果。.then()方法接受两个参数:一个用于处理成功结果的函数,一个用于处理失败结果的函数。

4. 手写Promise的实现。

class Promise {
  constructor(executor) {
    this.state = "pending"; // 初始状态为pending
    this.result = undefined; // 结果尚未确定
    this.successCallbacks = []; // 存储成功回调函数的数组
    this.failureCallbacks = []; // 存储失败回调函数的数组

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

  // resolve函数用于标记Promise为成功状态并存储结果
  resolve(result) {
    if (this.state !== "pending") return;

    this.state = "fulfilled"; // 将状态更改为fulfilled
    this.result = result; // 存储结果

    // 调用所有成功回调函数
    for (const callback of this.successCallbacks) {
      callback(result);
    }
  }

  // reject函数用于标记Promise为失败状态并存储错误原因
  reject(error) {
    if (this.state !== "pending") return;

    this.state = "rejected"; // 将状态更改为rejected
    this.result = error; // 存储错误原因

    // 调用所有失败回调函数
    for (const callback of this.failureCallbacks) {
      callback(error);
    }
  }

  // then方法用于添加成功回调函数和失败回调函数
  then(successCallback, failureCallback) {
    // 如果Promise已成功,则立即调用成功回调函数
    if (this.state === "fulfilled") {
      successCallback(this.result);
      return this;
    }

    // 如果Promise已失败,则立即调用失败回调函数
    if (this.state === "rejected") {
      failureCallback(this.result);
      return this;
    }

    // 如果Promise尚未完成,则将成功回调函数和失败回调函数存储起来,以便在Promise完成时调用它们
    this.successCallbacks.push(successCallback);
    this.failureCallbacks.push(failureCallback);

    return this;
  }
}

5. Promise面试题解析。

  • 如何处理Promise的并发执行?

可以使用Promise.all()方法来处理Promise的并发执行。Promise.all()方法接受一个Promise对象数组作为参数,并返回一个新的Promise对象。这个新的Promise对象将在所有传入的Promise对象都完成后完成。

  • 如何处理Promise的串行执行?

可以使用.then()方法来处理Promise的串行执行。.then()方法接受一个函数作为参数,这个函数将在传入的Promise对象完成后执行。

  • 如何处理Promise的超时?

可以使用.timeout()方法来处理Promise的超时。.timeout()方法接受一个数字作为参数,代表超时时间。如果Promise对象在超时时间内没有完成,则会触发超时错误。