Node.js Promise

Promise 是 Node.js 中处理异步操作的核心概念之一。

Promise 提供了一种更优雅的方式来管理异步代码,避免了传统的回调地狱(Callback Hell)问题。

本文将详细介绍 Promise 的概念、用法和常见模式。


什么是 Promise?

Promise 是一个表示异步操作最终完成或失败的对象。它有三种状态:

  1. Pending(等待中):初始状态,既不是成功,也不是失败
  2. Fulfilled(已成功):操作成功完成
  3. Rejected(已失败):操作失败

Promise 的状态一旦改变(从 pending 变为 fulfilled 或 rejected),就不会再改变。


创建 Promise

在 Node.js 中,可以使用 Promise 构造函数创建新的 Promise 对象:

实例

const myPromise = new Promise((resolve, reject) => {
  // 异步操作
  const success = true; // 假设这是异步操作的结果
 
  if (success) {
    resolve('操作成功!'); // 状态变为 fulfilled
  } else {
    reject('操作失败!'); // 状态变为 rejected
  }
});

使用 Promise

Promise 提供了 .then().catch() 方法来处理成功和失败的情况:

实例

myPromise
  .then((result) => {
    console.log(result); // 输出:"操作成功!"
  })
  .catch((error) => {
    console.error(error); // 输出:"操作失败!"
  });

Promise 链式调用

Promise 的强大之处在于可以链式调用多个异步操作:

实例

function asyncOperation1() {
  return new Promise((resolve) => {
    setTimeout(() => resolve('第一步完成'), 1000);
  });
}

function asyncOperation2(data) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(`${data}, 第二步完成`), 1000);
  });
}

asyncOperation1()
  .then((result) => asyncOperation2(result))
  .then((finalResult) => {
    console.log(finalResult); // 输出:"第一步完成, 第二步完成"
  })
  .catch((error) => {
    console.error('链式中出错:', error);
  });

Promise 的静态方法

Promise 提供了一些有用的静态方法:

Promise.all()

等待所有 Promise 完成,或任意一个 Promise 失败:

实例

const promise1 = Promise.resolve('第一个');
const promise2 = Promise.resolve('第二个');

Promise.all([promise1, promise2])
  .then((results) => {
    console.log(results); // 输出:['第一个', '第二个']
  });

Promise.race()

返回最先完成或失败的 Promise:

实例

const promise1 = new Promise((resolve) => setTimeout(resolve, 500, '第一个'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, '第二个'));

Promise.race([promise1, promise2])
  .then((result) => {
    console.log(result); // 输出:"第二个"
  });

错误处理

Promise 的错误处理可以通过 .catch().then() 的第二个参数实现:

实例

someAsyncFunction()
  .then(
    (result) => { /* 处理成功 */ },
    (error) => { /* 处理失败 */ }
  );

// 或者
someAsyncFunction()
  .then((result) => { /* 处理成功 */ })
  .catch((error) => { /* 处理所有错误 */ });

async/await 语法

ES2017 引入了 async/await 语法,让 Promise 的使用更加直观:

实例

async function runOperations() {
  try {
    const result1 = await asyncOperation1();
    const result2 = await asyncOperation2(result1);
    console.log(result2);
  } catch (error) {
    console.error(error);
  }
}

runOperations();

最佳实践

  1. 总是处理错误:不要忽略 .catch() 或 try-catch
  2. 避免嵌套:使用链式调用或 async/await 保持代码扁平
  3. 命名 Promise:给 Promise 变量起有意义的名称
  4. 返回 Promise:在函数中返回 Promise 以便链式调用