有什么方法可以同步等待或检查网络工作者中的新消息吗?
我有大量复杂的代码(从 emscripten 编译的 LLVM),我无法围绕回调进行重构。
我需要确保在我收到并处理来自 UI 线程的消息之前,某一行之后的代码不会执行。如果我用 while 循环阻塞,则事件循环永远不会运行,所以我无法接收消息。
有什么方法可以同步等待或检查网络工作者中的新消息吗?
我有大量复杂的代码(从 emscripten 编译的 LLVM),我无法围绕回调进行重构。
我需要确保在我收到并处理来自 UI 线程的消息之前,某一行之后的代码不会执行。如果我用 while 循环阻塞,则事件循环永远不会运行,所以我无法接收消息。
这是我在使用Pyodide时也遇到的问题。我想从主线程“同步”调用一个函数。
一种解决方案涉及Atomic
s 和SharedArrayBuffer
API。从 web worker 的角度来看,这看起来像下面这样
postMessage
主线程Atomics.wait
SharedArrayBuffer
。我们无法以 接收结果postMessage
,因为没有一种同步方式来询问“我收到消息了吗”。当然,这需要相当多的额外代码来处理所有的序列化、数据传递等等。
这样做的一个限制是它不能在 Safari 中工作,因为 Safari 没有实现Atomic
s API。另一个限制是,要使用这些 API,需要设置 COOP/COEP 标头。
还有一个带有同步 XHR 和 service worker的替代解决方案,但我还没有研究过这个选项。
Can you break the sequence as follow without refactoring?
wrk.onmessage = function(e) {
if (e.data.step === 'initial input') {
doInitialWork(e.data.inputs)
} else if (e.data.step === 'ui input') {
doTheRest(e.data.uiData)
}
}
The onmessage event will be blocked until the initial step execution stack is complete and the critical ui bits will only launch when and if the info is available.
不,不幸的是。有一些关于添加一种方法来阻止来自父页面的消息的讨论,但它没有成功。我会看看我是否可以挖掘相关的邮件列表线程。
一个粗略的破解方法可能是使用同步 API,例如 FileSystem API,并使用临时文件作为同步机制。
在您的示例中,emscripten 代码可以对文件发出同步读取,而 UI 线程写入同一个文件,从而有效地解除阻塞工作人员。
我就是这样做的。想到 Web Workers 还没有收到await 消息功能,真的很可悲,这将使整个线程间通信概念更接近例如Go语言。但是不,他们没有这样做,所以必须发明一些东西来保持线程同步
let resolver: any = undefined;
let message: any = undefined;
const messagePromise = new Promise((resolve) => resolver = resolve);
worker.onmessage = async ({ data: payload }: { data: any }) => {
message = payload;
worker.onmessage = undefined;
resolver?.();
}
await messagePromise;
现在,这是打字稿。只需删除类型即可获取 Javascript。请注意,如果在我们开始侦听消息之前已发送消息,则无法捕获该消息