英文:
Run Go-WebAssembly before onmessage event in a Web Worker
问题
我正在尝试在JavaScript Web Worker中包含一个Go-WebAssembly函数,问题是worker的onmessage事件在WebAssembly加载之前就运行了,所以每次调用WebAssembly函数时都会出现错误:"yourFunction未定义"。希望你能帮我找出如何解决这个问题,或者给我一些实现的思路。谢谢!
我简化了一下代码:
main.go
package main
import (
"fmt"
"log"
"syscall/js"
)
func myGoFunction(this js.Value, i []js.Value) interface{} {
//做一些复杂的工作
fmt.Println(i[0])
return true
}
func main() {
js.Global().Set("myGoFunction", js.FuncOf(myGoFunction))
<-make(chan bool)
}
main.js
const doSomething = () => {
if (myArray.length > 0)
worker.postMessage({ value: myArray.shift() })
}
const init = () => {
if (worker) worker.terminate()
worker = new Worker('worker.js')
worker.postMessage({ a: A, b: B, bool: true })
worker.onmessage = doSomething
}
init()
worker.js
importScripts('wasm_exec.js');
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
onmessage = (e) => {
const {settings} = e.data
if (settings) {
//设置一些值
} else {
for (let i= 0; i < 1000000; i++)
someArray[i] = calculate(i)
postMessage({someArray})
}
}
const calculate = (i) => {
//做更多的事情
//这里是我调用go函数的地方
myGoFunction(i)
}
为了查看myGoFunction是否加载,我尝试将WebAssembly.instantiateStreaming放入一个promise中,然后调用onmessage,但这样会导致WebAssembly.instantiateStreaming加载了数百万次,任务完成得非常慢。或者我可能错误地实现了promise。我不知道,请帮帮我。:D
英文:
I'm trying to include a Go-WebAssembly function inside a JavaScript Web Worker, and the problem is that the event onmessage from the worker runs before the WebAssembly loads so everytime I call the WebAssembly function I got an error: "yourFunction is not defined". I hope you can help me figuring out how to solve this problem or you can give me ideas how to implement this. Thanks !
A simplified version of my code:
main.go
package main
import (
"fmt"
"log"
"syscall/js"
)
func myGoFunction(this js.Value, i []js.Value) interface{} {
//Do some hard work
fmt.Println(i[0])
return true
}
func main() {
js.Global().Set("myGoFunction", js.FuncOf(myGoFunction))
<-make(chan bool)
}
main.js
const doSomething = () => {
if (myArray.length > 0)
worker.postMessage({ value: myArray.shift() })
}
const init = () => {
if (worker) worker.terminate()
worker = new Worker('worker.js')
worker.postMessage({ a: A, b: B, bool: true })
worker.onmessage = doSomething
}
init()
worker.js
importScripts('wasm_exec.js');
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
onmessage = (e) => {
const {settings} = e.data
if (settings) {
//set some values
} else {
for (let i= 0; i < 1000000; i++)
someArray[i] = calculate(i)
postMessage({someArray})
}
}
const calculate = (i) => {
//Do more
//Here is where I call the go function
myGoFunction(i)
}
Something I did to see if the myGoFunction is loading, is to put the WebAssembly.instantiateStreaming into a promise then call the onmessage but of course this will load the WebAssembly.instantiateStreaming millions of times and the job is done but extremely slow. Or maybe I implemented the promises the wrong way. I don't know, please help.
答案1
得分: 3
你可以将从WebAssembly.instantiateStreaming()
返回的Promise存储起来,并在你的onmessage
处理程序中等待它:
const waInit = WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
onmessage = async (e) => {
await waInit; // 现在 WA 已经准备好了
const {settings} = e.data
// 你处理程序的其余部分
}
英文:
You can store the promise returned from WebAssembly.instantiateStreaming()
and await it in your onmessage
handler:
const waInit = WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
onmessage = async (e) => {
await waInit; // now WA is ready
const {settings} = e.data
// The rest of your handler
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论