如何在网络工作者中使用WebAssembly(wasm)代码?

17

目前,Web Worker是这样实例化的:

let worker = new Worker('worker.js');

浏览器会获取 worker.js ,并开始响应消息。

我想使用 WebAssembly 实现我的 worker 功能。理想情况下,我希望做到这一点:

let worker = new Worker('worker.wasm');

但我非常确定这是不可能的。最明显的替代方案是让 worker.js 获取 worker.wasm 并编译和运行它。但这意味着我们要获取一个脚本 (worker.js) ,其唯一工作是获取并运行另一个脚本 (worker.wasm)。这对我来说感觉很恶心。所以我的问题是:在 Web Worker 中使用 WebAssembly 是否有更干净的方式,而不会引入额外的获取步骤?


那么我的问题是:是否有更干净的使用WebAssembly在Web Worker中的方法,而不会引入额外的获取步骤?如果Worker不打算使用,那么首先使用Worker的目的是什么?问题陈述中没有实际的问题存在。 - guest271314
@guest271314,其中一个好处是wasm将在不同的线程中运行。 - nalply
也许你可以把wasm放在SharedArrayBuffer中,我没有尝试过,但我可以想象使用SharedArrayBuffer不需要复制。 - nalply
这个代码库包含了一些使用Web Workers和Wasm(从Rust编译而来)的示例:https://github.com/sgasse/wasm_worker_interaction - Matthias Braun
1个回答

2
你可以向Worker发送一个WebAssembly.Module,因此你需要在主脚本中编译foo.wasm,然后将其postMessage。实现预计会进行优化,以避免重新编译或复制代码(尽管目前并非所有实现都这样做)。然后您只需要让工作线程实例化即可。
实例化所需的一个内容是importObject,您传递的内容需要驻留在该工作线程中!因此,即使您可以说“使用此.wasm创建新工作线程”,也没有办法指定importObject
这在结构化克隆中有记录,它也会影响IndexDB。

我不确定这是否有效。当我尝试在postMessage中发送一个wasm Module时,我会得到以下错误:example.js:54 Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'Worker': () => resolve(Module) could not be cloned. at http://localhost:8000/example.js:13702:31 at <anonymous> - Josh Hansen
我整理了我的代码,并使用 WebAssembly.compile 生成了一个模块。然后,我尝试通过 postMessage 发送它,但是出现了这个错误:Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'Worker': An object could not be cloned. - Josh Hansen
那是在Chrome 60下的情况。Chrome 62会出现Uncaught(在promise中)DOMException:无法执行“postMessage”操作的“Worker”:#<Module>无法被克隆。Firefox 57.0b14似乎可以正常工作。 - Josh Hansen
1
那听起来像是Chrome的漏洞。 - JF Bastien
1
https://github.com/nodeca/pica/blob/3.0.6/index.js#L322 在 Chrome 中,wasm 对象传输对我有效。但是我在包的下一个版本中放弃了它。Browserify + webworkify 已经足够好了(它可以从主线程中的模块动态创建 ww src)。在我看来,为小模块增加额外的编译步骤是便宜且简单的选择。 - Vitaly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接