async/await 能替代 Promise.then 且更直观,本质是 Promise 的语法包装;await 只能在 async 函数中使用,顶层 await 需 ES 模块支持;需用 try/catch 正确捕获错误,注意并发控制与错误隔离。
能,而且更直观。async/await 不是新语法糖,而是 Promise 的语法包装,底层完全基于 Promise。只要函数用 async 声明,它就自动返回一个 Promise;在函数体内用 await 等待的值,无论原本是不是 Promise,都会被自动 Promise.resolve() 包裹。
直接在模块顶层写 await 会报错 SyntaxError: await is only valid in async function,除非你:
.mjs 文件或 type="module" 的 script 标签中)启用顶层 await —— 这是合法的,且浏览器和 Node.js 14.8+ 都支持;(async () => {
const data = await fetch('/api/user').then(r => r.json())
console.log(data)
})()async 函数,而非依赖顶层 await
误边界await 后抛出的错误不会冒泡到外层同步代码,必须用 try/catch 捕获。这比链式 .catch() 更贴近同步思维,但也容易误以为“没写 catch 就不会出错”。
常见疏忽:
await fetch(),但后续 res.json() 可能失败,也要在同一个 try 块里Promise.allSettled() 或单独 try/catch 每次调用await 后接的是可能为 undefined 或 null 的值时,直接链式调用会报 Cannot read property 'xxx' of undefined,这不是 Promise rejection,catch 捕不到连续写多个 await 是串行执行,耗时累加;想并行,得先发起所有 Promise,再统一 await:
const [user, posts, comments] = await Promise.all([
fetch('/api/user').then(r => r.json()),
fetch('/api/posts').then(r => r.json()),
fetch('/api/comments').then(r => r.json())
])
关键点:
Promise.all() 任意一个 reject 整体就失败;需要全部结果(含失败)请改用 Promise.allSettled()
await 后跟普通函数调用(如 await fs.readFile())仍是异步,但若该函数内部没真正异步(比如只是同步计算),await 就失去意义,还可能误导可读性