My Personal Blog

Published on

Promise 是什么?有什么用途?

Authors
  • avatar
    Name
    Tian Haipeng

为什么要使用 Promise?

在了解 Promise 之前,先来看一下为什么需要它的出现。

JavaScript 是单线程语言,异步操作(如文件操作、数据库操作、AJAX 请求、定时器等)是不可避免的。异步操作允许 JavaScript 在执行耗时任务时,不必阻塞主线程,而是可以继续执行其他代码,任务完成后再通知程序。

在 ES6 之前,通常使用回调函数(callback)来处理异步操作,但这种写法在处理多重嵌套时,会导致“回调地狱”(callback hell)现象,代码难以维护。比如下面的代码:

callback(() => {
  console.log("Hello!");
  callback(() => {
    console.log("Hello!");
    callback(() => {
      console.log("Hello!");
      callback(() => {
        console.log("Hello!");
      }, 200);
    }, 200);
  }, 200);
}, 200);

为了避免回调地狱,Promise 被引入来改善代码的可读性和可维护性。

什么是 Promise?

Promise 是一种用于处理异步操作的对象,它代表一个尚未完成的操作,并允许在操作完成后处理成功或失败的结果。Promise 主要解决了异步编程中代码嵌套过深和错误处理困难的问题。

如何使用 Promise?

Promise 是一个构造函数,可以通过 new 关键字来创建。它接受一个函数作为参数,这个函数被称为执行器(executor),并会立即执行。

new Promise((resolve, reject) => {
  console.log("executor 立即执行");
});

执行器函数有两个参数:resolverejectresolve 用于表示操作成功,reject 用于表示操作失败。比如:

function requestData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url === "example.com") {
        resolve("Success: Data fetched!");
      } else {
        reject("Error: Invalid URL");
      }
    }, 3000);
  });
}

// 请求成功
requestData("example.com").then((res) => {
  console.log(res); // Success: Data fetched!
});

// 请求失败
requestData("wrong-url.com").catch((error) => console.log(error)); // Error: Invalid URL

Promise 的三种状态

一个 Promise 对象有三种状态:

  1. pending:初始状态,表示操作尚未完成。
  2. fulfilled:操作成功,调用了 resolve
  3. rejected:操作失败,调用了 reject

使用 .then() 处理异步结果

then() 方法用于注册回调函数,在 Promise 完成后执行。它接受两个参数:第一个是成功时的回调,第二个是失败时的回调。

requestData("example.com").then(
  (res) => {
    console.log(res);
  },
  (error) => {
    console.log(error);
  }
);

链式调用

then() 可以链式调用,多个异步操作可以通过这种方式串联起来,避免回调地狱。例如:

requestData("example.com")
  .then((res) => {
    console.log(res);
    return 1;
  })
  .then((res) => {
    console.log(res); // 1
    return 2;
  })
  .then((res) => {
    console.log(res); // 2
  });

错误处理

Promise 的另一个优点是可以统一处理错误。通过 .catch() 方法,可以捕获异步操作中的错误并处理。

fetch("https://example.com/data")
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

finally() 方法

finally() 方法用于在 Promise 的状态无论是成功还是失败时,都要执行的代码。比如关闭加载动画等。

fetch("https://example.com/data")
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.error("Error:", error);
  })
  .finally(() => {
    console.log("操作结束,关闭加载动画");
  });

什么是 async/await?

async/await 是基于 Promise 的语法糖,使得异步代码看起来更像是同步代码。async 关键字标记的函数会返回一个 Promise,而 await 用于等待 Promise 的完成。

async function fetchData() {
  const res = await fetch("https://example.com/data");
  const data = await res.json();
  console.log(data);
}

fetchData();

通过 async/await,可以让异步代码更简洁,同时也更容易处理错误和调试。

总结

  • Promise 是用于处理异步操作的对象,解决了回调地狱问题。
  • 它有三种状态:pendingfulfilledrejected
  • Promise 支持链式调用,可以通过 .then().catch().finally() 来处理异步结果和错误。
  • async/await 是 Promise 的语法糖,使异步代码更直观。