跳转到主内容
极星编程网:以代码为星,赴技术山海!

Async/Await是什么_如何让异步代码更易读【教程】

async/await 是 Promise 的语法封装而非新语法糖,async 函数自动将返回值包装为 Promise,await 只能在 async 函数内使用,需注意串行与并发区别及错误处理机制。 Async/await 不是新语法糖,而是 Promise 的语法封装,它本身不改变异步行为,但能显著降低回调嵌套和
.then()
链的维护成本。 async 函数必须显式返回 Promise 声明为
async
的函数,无论内部是否
await
,其返回值都会被自动包装成 Promise。这意味着: 直接
return 42
→ 实际返回
Promise.resolve(42)
return Promise.reject(new Error())
不会再被包装,原样传出 如果忘记
await
一个 async 函数调用,你拿到的是一个 pending 的 Promise,不是结果
async function getValue() { return "done"; } console.log(getValue()); // Promise {} console.log(await getValue()); // "done"
await 只能在 async 函数内使用 试图在普通函数或顶层 作用域 中写
await
会触发
SyntaxError: await is only valid in async functions
。常见误用场景包括: 在
if
或
for
块里直接
await
(没包 async 函数) Node. js 14.8+ 支持顶层 await,但仅限 ES 模块(
type: "module"
),CommonJS 中仍非法 React 事件 处理器 如
onClick={() => await handleSubmit()}
会报错,必须写成
onClick={async () => {...}}
错误处理:不要只靠 try/catch,也要检查 rejected 状态
await
会让 rejected Promise 抛出异常,所以
try/catch
是主流做法。但要注意: php版微信js-sdk支付接口类 php版微信js-sdk支付接口类 下载
await Promise.all([p1, p2])
任一失败即整体 reject,无法获知哪个出错 —— 改用
Promise.allSettled()
更稳妥 对可能为
null
或非 Promise 的值调用
await
不会报错,但无意义(
await 123
直接返回
123
) 未捕获的 Promise rejection 会触发
unhandledrejection
事件,在 Node.js 中可能导致进程退出
async function fetchBoth() { try { const [a, b] = await Promise.allSettled([ fetch("/api/user"), fetch("/api/posts") ]); if (a.status === "fulfilled") console.log(a.value); if (b.status === "rejected") console.error(b.reason); } catch (e) { // 这里不会捕获 Promise.allSettled 的 rejection } }
性能陷阱:await 并不自动并发,顺序写 = 串行执行 这是最常被忽略的一点:
await
是阻塞当前 async 函数执行流的,但不阻塞整个线程。连续写多个
await
就是串行,不是并行: ❌ 错误示范(耗时 = t1 + t2):
const a = await fetch("/a"); const b = await fetch("/b");
✅ 正确做法(耗时 ≈ max(t1, t2)):
const [a, b] = await Promise.all([fetch("/a"), fetch("/b")]);
若需按序处理但又想提前发起请求,先发请求再
await
:
const promiseA = fetch("/a"); const promiseB = fetch("/b"); const a = await promiseA; const b = await promiseB;
真正难的不是写
async/await
,而是判断哪些操作该并发、哪些必须串行、哪些根本不需要
await
—— 这些决定直接影响响应时间和资源利用率。

相关文章