最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何正确使用 await 关键字让当前异步函数的执行上下文线程平滑挂起
时间:2026-06-20 10:38:47 编辑:袖梨 来源:一聚教程网
await挂起异步函数执行上下文而非线程,仅限async函数内使用;等待Promise或thenable对象,后续代码作为微任务执行,不阻塞主线程。
await 不会挂起“线程”,它挂起的是当前 异步函数的执行上下文,让出控制权给事件循环,以便其他任务可以运行。JavaScript 是单线程的,没有真正的线程概念(主线程上无多线程抢占),所以“挂起线程”这种说法容易引发误解。
await 只能在 async 函数内部使用
这是语法硬性要求。直接在普通函数或顶层作用域写 await somePromise() 会报语法错误。
- 正确写法:
async function foo() { await fetch('/api'); } - 错误写法:
function bar() { await fetch('/api'); }(SyntaxError) - 顶层 await 仅限模块作用域(ESM 模块中允许),但不等同于在普通脚本中随意使用
await 等待的是“thenable”对象,本质是 Promise 状态流转
await 后面表达式会被自动 Promise.resolve() 包装。它真正等待的是该 Promise 进入 fulfilled 或 rejected 状态。
-
await 123→ 等价于await Promise.resolve(123),立刻继续执行 -
await fetch(url)→ 等待网络响应完成并返回 Response 对象 -
await new Promise(r => setTimeout(r, 1000))→ 等待 1 秒后 resolve
await 之后的代码会被放入微任务队列,而非立即执行
当 await 后的 Promise 完成时,后续语句不会立刻同步运行,而是作为微任务(microtask)被调度,在当前同步代码结束后、下一次宏任务(如 setTimeout)之前执行。
- 这意味着:await 不阻塞浏览器渲染或事件响应,UI 仍可交互
- 多个 await 串行执行时,每个 await 都会“暂停”函数体,但不会冻结整个 JS 引擎
- 例如:
await a(); console.log('1'); await b(); console.log('2');中,'1' 一定在 a() 的 Promise fulfilled 后打印,'2' 同理
避免常见误用:不要用 await 包裹非 Promise 值做“伪等待”
比如 await setTimeout(...) 是无效的——setTimeout 返回的是定时器 ID(数字),不是 Promise,await 会立刻解包并继续,达不到延时效果。
- 正确延时写法:
await new Promise(r => setTimeout(r, 1000)); - 错误写法:
await setTimeout(() => {}, 1000);(毫无等待作用) - 对已 resolve 的 Promise 使用 await 无性能损失,但对纯同步值(如字符串、对象)使用 await 无实际意义
理解 await 的本质是“暂停函数执行、交还控制权、等待 Promise settled 后恢复”,比记住“挂起线程”更准确也更实用。
相关文章
- 鹅鸭杀手游古代沙漠地图任务地点一图解 06-27
- 我的扬州app如何查社保 06-27
- 宝可梦pokopia环境湿润的宝可梦都有哪些 06-27
- Kicks 将接替 wayne 参加 Team Liquid 的首场 Kickoff 比赛 06-27
- 怎么在 2XKO 中免费解锁凯特琳 06-27
- 《马拉松》成为多个地区预订量最高的PS5游戏之一 06-27