我知道在正常的 dom 范围内,你不能在同步函数中等待异步结果,因为这会阻塞 UI。
现在,在网络工作者中可以阻塞线程。有没有什么方法可以在不使用await/async的情况下等待异步结果?我也在寻找黑客......
我的解决方案已经使用await/async/Promise 运行良好。我想避免等待的原因是我为用户提供了编写在 Web Worker 中执行的代码的可能性。由于小学生也是我的受众的一部分,我希望让事情变得简单,而不必仅仅因为他们应该能够执行异步函数而引入整个 Promise 概念。
我想模仿你可以说的同步 Api。但在他们应该调用的函数的核心中有异步代码......
我理解为什么 JS 是这样设计的,但对我来说,系统保护我在可以阻塞线程的情况下(Web Worker)不阻塞线程,这让我感觉很愚蠢......
谢谢 卢卡斯
是的,您可以使用 Atomics.wait、Atomics.notify 和 SharedArrayBuffer。
方法如下:
将这些标头设置为您提供的 html,因为由于 Spectre bug,SharedArrayBuffer 仅在跨源隔离环境中可用。
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
它会生成一个带有 doSomething 消息处理程序的工作线程。
const worker = new Worker(new URL("/worker.mjs", location.href));
worker.addEventListener("message", async (event) => {
console.log("event", event);
if (event.type === "doSomething") {
await doSomething();
Atomics.notify(new Int32Array(event.sab), 0);
}
});
const doSomething = async () => {
console.log("doing something...");
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("did something.");
};
将
<script>
标签添加到 html 中以加载此内容。
它创建一个 SharedArrayBuffer 并将其与主线程共享,然后等待通知。
console.log("I am a worker");
const sab = new SharedArrayBuffer(4);
postMessage({ type: "doSomething", sab });
Atomics.wait(new Int32Array(sab), 0, 0);
console.log("done");
它显示了这一点并同步等待主线程。
I am a worker
event {
type: 'doSomething',
sab: SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }
}
doing something...
(1s later)
did something.
done