Atomics.waitAsync 不能在主线程使用,是浏览器安全模型的硬性限制;它专为 Worker 设计,依赖 SharedArrayBuffer 和底层线程调度器,主线程既无权限访问共享内存,也不具备对应挂起/唤醒原语。

Atomics.waitAsync 不能在主线程使用,这是硬性限制。你试图在主线程调用它,一定会抛 TypeError: Atomics.waitAsync is not supported,不是环境没配好,而是浏览器根本禁止——它专为 Worker 设计。
为什么主线程调用 Atomics.waitAsync 必然失败
根本原因不是 JS 层逻辑问题,而是浏览器安全模型:主线程默认无权访问 SharedArrayBuffer,而 Atomics.waitAsync 依赖它。即使你手动写了 new SharedArrayBuffer(4),只要页面没启用跨源隔离(COOP/COEP),构造就会静默失败或直接报错。更关键的是,Atomics.waitAsync 的实现绑定在 Worker 线程的底层调度器上,主线程事件循环不提供对应挂起/唤醒原语。
验证方式很简单:
- 运行
typeof SharedArrayBuffer !== 'undefined'—— 若为false,说明隔离未启用 - 检查
Atomics.waitAsync是否为函数 —— 主线程里永远是undefined - 服务器响应头必须含
Cross-Origin-Opener-Policy: same-origin和Cross-Origin-Embedder-Policy: require-corp - 本地开发不能用
file://,得跑python3 -m http.server 8000 --bind 127.0.0.1这类服务
Worker 中正确发起异步等待的三步操作
等待逻辑必须写在 async 函数内,且严格遵循“先读再等”原则。跳过 Atomics.load 直接 waitAsync,会错过初始值变更,导致永远 pending。
典型流程:
- 主线程创建缓冲区:
const sab = new SharedArrayBuffer(4); const iv = new Int32Array(sab); Atomics.store(iv, 0, 0);,再通过postMessage({ sab })发给 Worker - Worker 接收后建立一致视图:
const iv = new Int32Array(e.data.sab);(必须是Int32Array,不能混用Uint32Array) - 等待前确认当前值:
const current = Atomics.load(iv, 0); if (current !== 0) { /* 已变更,无需等 */ } else { const { value, asyncId } = await Atomics.waitAsync(iv, 0, 0); }
Atomics.notify 不匹配就等于没通知
通知方和等待方必须完全对齐:同一块 SharedArrayBuffer、同一字节偏移(这里是索引 0)、同一数据类型视图。哪怕只差一个字节偏移,notify 就不会唤醒任何 waitAsync。
常见错误:
- 通知时用了
Atomics.notify(iv, 0, 1),但等待方传的是0以外的预期值(比如Atomics.waitAsync(iv, 0, 1)) - 主线程用
Uint8Array写值,Worker 用Int32Array等待 —— 字节解释不同,load结果错乱 - 通知发生在
waitAsync调用之前,或发生在另一个独立的Int32Array视图上 - 漏加超时保护:应包裹在
Promise.race([waitAsync(...), new Promise((_, r) => setTimeout(r, 5000))])里
主线程如何安全参与同步而不越界
主线程不能等,但可以发信号、查状态、做协调。它的角色是“调度者”,不是“等待者”。
可行做法:
- 用
Atomics.store(iv, 0, 1)主动触发 Worker 中的waitAsync唤醒(前提是 Worker 已开始等待) - 用
Atomics.load(iv, 0)轮询检查 Worker 是否完成(仅限低频、非实时场景;高频轮询不如postMessage) - Worker 完成后主动
postMessage通知主线程,主线程用Promise.withResolvers()(ES2024)管理等待链 - 避免在主线程尝试模拟“等待”——没有
Atomics.waitAsync,也没有安全可靠的替代方案
最易被忽略的一点:所有共享内存访问都必须走 Atomics.load/Atomics.store,裸读写 iv[0] 会破坏原子性,尤其在多 Worker 场景下极易引发竞态。


















