Node.js async/await

把 Promise 写成同步的样子,同时保住并发能力。

Intermediate
Key Points`await` 只是 `.then` 的语法糖;真正的并发要靠先发起、后 `await`。

基本形态

JavaScript
async function getUser(id) {
  const res = await fetch(`https://api.example.com/users/${id}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

try {
  const user = await getUser(1);
  console.log(user.name);
} catch (e) {
  console.error('失败:', e.message);
}

An async function always returns a Promise. return 1 is Promise.resolve(1); throw e is Promise.reject(e). So callers must await it or .catch it.

并发:先发起,后等待

JavaScript
// 慢:总共 3 秒
const a = await task('a', 1000);
const b = await task('b', 1000);
const c = await task('c', 1000);

// 快:总共 1 秒
const [x, y, z] = await Promise.all([task('a', 1000), task('b', 1000), task('c', 1000)]);
Output
串行总耗时 3003 ms
并发总耗时 1002 ms

给 await 加超时

JavaScript
function withTimeout(promise, ms, label = '操作') {
  const timer = new Promise((_, reject) =>
    setTimeout(() => reject(new Error(`${label}超时 ${ms}ms`)), ms)
  );
  return Promise.race([promise, timer]);
}

await withTimeout(fetch('https://example.com'), 3000, '请求');
A Promise.race timeout does not actually abort the underlying request — it only makes await return early. To abort, pass signal: AbortSignal.timeout(3000).

几个语法细节

CaseRule
顶层 awaitESM 里可以直接用;CommonJS 不行
await 非 Promise原值直接返回,不报错
forEach + async不会等待,改用 for...of
try/finally可以,用来释放连接
JavaScript
// 连接池必须 finally 释放,否则出错时泄漏
const conn = await pool.getConnection();
try {
  const [rows] = await conn.query('SELECT 1');
  return rows;
} finally {
  conn.release();
}

Friends & Partners