Node.js async/await
把 Promise 写成同步的样子,同时保住并发能力。
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).几个语法细节
| Case | Rule |
|---|---|
| 顶层 await | ESM 里可以直接用;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();
}基本形态
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);
}async 函数永远返回 Promise。return 1 等于 Promise.resolve(1),throw e 等于 Promise.reject(e)。所以在外面要么 await 它,要么 .catch 它。
并发:先发起,后等待
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, '请求');Promise.race 做超时不会真的中止底层请求,只是让 await 提前返回。要中止 HTTP 请求得传 signal: AbortSignal.timeout(3000)。几个语法细节
| 场景 | 规则 |
|---|---|
| 顶层 await | ESM 里可以直接用;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();
}