在 webworker 的同步函数中等待异步执行(javascript)

问题描述 投票:0回答:1

我知道在正常的 dom 范围内,你不能在同步函数中等待异步结果,因为这会阻塞 UI。

现在,在网络工作者中可以阻塞线程。有没有什么方法可以在不使用await/async的情况下等待异步结果?我也在寻找黑客......

我的解决方案已经使用await/async/Promise 运行良好。我想避免等待的原因是我为用户提供了编写在 Web Worker 中执行的代码的可能性。由于小学生也是我的受众的一部分,我希望让事情变得简单,而不必仅仅因为他们应该能够执行异步函数而引入整个 Promise 概念。

我想模仿你可以说的同步 Api。但在他们应该调用的函数的核心中有异步代码......

我理解为什么 JS 是这样设计的,但对我来说,系统保护我在可以阻塞线程的情况下(Web Worker)不阻塞线程,这让我感觉很愚蠢......

谢谢 卢卡斯

javascript asynchronous async-await web-worker synchronous
1个回答
0
投票

是的,您可以使用 Atomics.waitAtomics.notifySharedArrayBuffer

方法如下:

启用跨源隔离

将这些标头设置为您提供的 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
© www.soinside.com 2019 - 2024. All rights reserved.