全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-15 10 分钟 ✍️ juanwangdev

Node.js Promise与async/await深入

深入理解 Promise 和 async/await 的内部机制,写出更高效的异步代码。

Promise 状态机

JavaScript
// Promise 三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

// 状态转换规则:
// pending → fulfilled(不可逆)
// pending → rejected(不可逆)

// 状态只能转换一次
const p = new Promise((resolve, reject) => {
  resolve('成功'); // 状态变为 fulfilled
  reject('失败');  // 无效,状态已确定
});

Promise 链式调用原理

JavaScript
// then 返回新 Promise
Promise.resolve(1)
  .then(x => x + 1)  // 返回 Promise(2)
  .then(x => x * 2)  // 返回 Promise(4)
  .then(console.log); // 4

// 每个 then 创建新 Promise
// 前一个 Promise 的结果传递给下一个

值穿透

JavaScript
// then 不传回调时,值会穿透
Promise.resolve(1)
  .then()           // 穿透
  .then()           // 穿透
  .then(console.log); // 1

// 等价于
Promise.resolve(1)
  .then(x => Promise.resolve(x))
  .then(x => Promise.resolve(x))
  .then(console.log);

Promise 解析

JavaScript
// then 回调返回 Promise 时会等待解析
Promise.resolve(1)
  .then(x => new Promise(resolve => {
    setTimeout(() => resolve(x + 1), 1000);
  }))
  .then(console.log); // 2(等待 1 秒)

// 返回值是 Promise 时,会等待其完成

Promise 错误冒泡

JavaScript
// 错误会沿链冒泡
Promise.reject(new Error('失败'))
  .then(() => console.log('跳过'))
  .then(() => console.log('跳过'))
  .catch(err => console.log('捕获:', err.message));

// catch 后可继续
Promise.reject(new Error('失败'))
  .catch(err => '恢复')
  .then(result => console.log(result)); // '恢复'

未处理的拒绝

JavaScript
// 未处理的 Promise 拒绝
process.on('unhandledRejection', (reason, promise) => {
  console.error('未处理的拒绝:', reason);
});

// 避免未处理的拒绝,始终添加 catch

Promise.all 实现

JavaScript
// Promise.all 并行执行
Promise.all([
  fetch('/api/users'),
  fetch('/api/posts')
])
  .then(([users, posts]) => {
    // 全部成功
  })
  .catch(err => {
    // 任一失败立即触发
  });

// 手动实现
function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    let completed = 0;

    promises.forEach((p, i) => {
      Promise.resolve(p).then(result => {
        results[i] = result;
        completed++;
        if (completed === promises.length) {
          resolve(results);
        }
      }).catch(reject);
    });
  });
}

Promise.race 实现

JavaScript
// Promise.race 返回最先完成的结果
Promise.race([
  fetch('/api/fast'),
  new Promise((_, reject) =>
    setTimeout(() => reject(new Error('超时')), 5000)
  )
]);

// 手动实现
function promiseRace(promises) {
  return new Promise((resolve, reject) => {
    promises.forEach(p => {
      Promise.resolve(p).then(resolve).catch(reject);
    });
  });
}

async 函数原理

JavaScript
// async 函数返回 Promise
async function foo() {
  return '结果';
}

// 等价于
function foo() {
  return Promise.resolve('结果');
}

// await 暂停函数执行
async function bar() {
  const result = await promise;
  // 等待 promise 完成后继续
}

async 执行流程

JavaScript
async function example() {
  console.log('A');
  await Promise.resolve();
  console.log('B');
}

example();
console.log('C');

// 执行顺序:
// A (同步执行到 await)
// C (await 后的代码作为微任务)
// B (微任务执行)

await 并行优化

JavaScript
// ❌ 顺序 await(串行)
async function serial() {
  const a = await fetchA(); // 1秒
  const b = await fetchB(); // 1秒
  return [a, b]; // 总耗时 2秒
}

// ✅ 并行 await
async function parallel() {
  const [a, b] = await Promise.all([
    fetchA(),
    fetchB()
  ]);
  return [a, b]; // 总耗时 1秒
}

// ✅ 先发起再 await
async function optimized() {
  const pA = fetchA();
  const pB = fetchB();
  const a = await pA;
  const b = await pB;
  return [a, b]; // 总耗时 1秒
}

错误处理策略

JavaScript
// try-catch 捕获 await 错误
async function withTryCatch() {
  try {
    const data = await fetchData();
    return processData(data);
  } catch (err) {
    console.error('错误:', err);
    throw err;
  }
}

// .catch() 捕获 Promise 错误
async function withCatch() {
  const data = await fetchData().catch(err => {
    console.error('错误:', err);
    return null; // 恢复默认值
  });
  return data;
}

// 包装器模式
async function withWrapper(fn) {
  try {
    return await fn();
  } catch (err) {
    logger.error(err);
    return null;
  }
}

Promise 性能考量

JavaScript
// Promise 创建开销
// 避免 Promise 包装同步操作

// ❌ 不必要的 Promise
function syncOperation() {
  return Promise.resolve(syncWork());
}

// ✅ 直接返回
function syncOperation() {
  return syncWork();
}

// 使用 async_hooks 监控
const asyncHooks = require('async_hooks');
const hook = asyncHooks.createHook({
  init(asyncId, type) {
    if (type === 'PROMISE') {
      console.log('Promise 创建:', asyncId);
    }
  }
});

要点总结

  • Promise 状态只能转换一次,pending → fulfilled/rejected
  • then 返回新 Promise,形成链式调用
  • 错误沿链冒泡,catch 可捕获恢复
  • async 函数返回 Promise,await 暂停执行
  • await 后代码作为微任务执行
  • 并行操作使用 Promise.all 或先发起再 await

📝 发现内容有误?点击此处直接编辑

← 上一篇 Node.js 进程间通信
下一篇 → Node.js process.nextTick
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库