在 Web Worker 中的 onmessage 事件之前运行 Go-WebAssembly。

huangapple go评论78阅读模式
英文:

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 (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;syscall/js&quot;
)

func myGoFunction(this js.Value, i []js.Value) interface{} {
	//Do some hard work
    fmt.Println(i[0])
	return true
}

func main() {
	js.Global().Set(&quot;myGoFunction&quot;, js.FuncOf(myGoFunction))
	&lt;-make(chan bool)
}

main.js

const doSomething = () =&gt; {
if (myArray.length &gt; 0)
    worker.postMessage({ value: myArray.shift() })
}

const init = () =&gt; {
    if (worker) worker.terminate()
    worker = new Worker(&#39;worker.js&#39;)
    worker.postMessage({ a: A, b: B, bool: true })
    worker.onmessage = doSomething
}

init()

worker.js

importScripts(&#39;wasm_exec.js&#39;);

const go = new Go();
WebAssembly.instantiateStreaming(fetch(&quot;main.wasm&quot;), go.importObject).then((result) =&gt; {
    go.run(result.instance);
});

onmessage = (e) =&gt; {

    const {settings} = e.data
    
    if (settings) {
       //set some values
    } else {

      for (let i= 0; i &lt; 1000000; i++)
        someArray[i] = calculate(i)

        postMessage({someArray})
    }
}

const calculate = (i) =&gt; {
   //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. 在 Web Worker 中的 onmessage 事件之前运行 Go-WebAssembly。

答案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(&quot;main.wasm&quot;), go.importObject).then((result) =&gt; {
  go.run(result.instance);
});
onmessage = async (e) =&gt; {
  await waInit; // now WA is ready
  const {settings} = e.data
  // The rest of your handler

huangapple
  • 本文由 发表于 2022年9月14日 10:58:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/73711027.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定