SharedArrayBuffer 配合 Atomics.waitAsync 可实现 Worker 间非阻塞、基于 Promise 的等待同步机制,需跨域隔离(COOP/COEP)、同源 SharedArrayBuffer 及现代浏览器支持;核心是用 Int32Array 信号位配合 waitAsync/notify,推荐封装为带超时与取消的 AsyncSignal 类,并注意虚假唤醒、通知时序与内存生命周期管理。

SharedArrayBuffer 配合 Atomics.waitAsync 可以在 Worker 之间实现**非阻塞、基于 Promise 的等待同步机制**,避免传统 Atomics.wait 的线程挂起问题,特别适合需要响应式协调多个 Worker 任务的场景(如渲染流水线、多阶段数据处理、协作式调度)。
核心前提:启用跨域隔离与共享内存支持
Atomics.waitAsync 是现代浏览器中受严格限制的 API,必须满足以下条件才能使用:
- 页面需通过 COOP/COEP 头启用跨域隔离(
Cross-Origin-Opener-Policy: same-origin+Cross-Origin-Embedder-Policy: require-corp) - SharedArrayBuffer 必须由主线程或 Worker 显式创建并传递(不能跨域 iframe 直接访问)
- 目标浏览器需支持
Atomics.waitAsync(Chrome 93+、Firefox 109+、Safari 16.4+,需开启实验性功能标志的旧版本除外)
基础通信结构:共享状态 + 异步等待循环
两个 Worker 共享一个 Int32Array 视图(通常用 0 号元素作信号位),一方调用 Atomics.waitAsync 等待值变化,另一方用 Atomics.store 或 Atomics.add 修改并唤醒:
// Worker A(等待方)
const sab = new SharedArrayBuffer(4);
const view = new Int32Array(sab);
<p>// 等待 view[0] 变为 1(带超时)
async function waitForSignal() {
while (Atomics.load(view, 0) !== 1) {
const result = await Atomics.waitAsync(view, 0, 0); // 等待从 0 → 非0
if (result.async === false && result.wakeCount > 0) {
break; // 被正常唤醒
}
}
console.log('收到信号');
}</p><p>waitForSignal();
</p>
// Worker B(通知方)
const sab = /* 同一 SharedArrayBuffer */;
const view = new Int32Array(sab);
<p>// 发送信号
setTimeout(() => {
Atomics.store(view, 0, 1);
Atomics.notify(view, 0, 1); // 唤醒最多 1 个等待者
}, 1000);
</p>
实用技巧:构建可复用的异步信号类
手动轮询 + waitAsync 容易出错。推荐封装成 Promise 化信号对象,支持多次触发、取消、超时:
AI 舌诊面诊问诊医疗系统 + 诊疗商城系统源码是一套结合 AI 辅助诊断与商品转化的健康类程序,基于浩创云、ThinkPHP(PHP)开发,支持微信服务号与 H5 端,适合做中医舌诊面诊问答、健康建议推送以及配套诊疗商品的运营。
class AsyncSignal {
constructor(sab) {
this.view = new Int32Array(sab);
this.aborted = false;
}
<p>async wait(expected = 0, timeoutMs = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);</p><pre class="brush:php;toolbar:false;">try {
while (!this.aborted && Atomics.load(this.view, 0) !== expected) {
const result = await Atomics.waitAsync(this.view, 0, Atomics.load(this.view, 0));
if (result.async === false || result.wakeCount > 0) break;
}
return Atomics.load(this.view, 0) === expected;
} finally {
clearTimeout(timeoutId);
}
}
notify(value) { Atomics.store(this.view, 0, value); Atomics.notify(this.view, 0, 1); }
abort() { this.aborted = true; } }
使用时只需传入同一 SharedArrayBuffer 实例,Worker 间即可解耦通信逻辑。
注意事项与常见陷阱
实际使用中需警惕以下问题:
-
不要依赖 Atomics.waitAsync 的返回值判断值是否已变 —— 它只表示“被唤醒”,需再次
Atomics.load检查当前值(防止虚假唤醒或竞争) - 避免在同一个位置频繁 notify + wait —— 若 notify 先于 wait 执行,waitAsync 将永久挂起(无自动重试)。建议采用“先设值再 notify”且等待方主动轮询初始状态
- SharedArrayBuffer 生命周期需由创建方管理 —— 若主线程释放了 sab,所有 Worker 的 view 将变为不可访问(抛出 TypeError)
- 不支持 transferable 的 waitAsync 参数 —— sab 必须提前共享,不能在 postMessage 中动态 transfer 后再调用










