web worker 使用 web assembly 时出错

Error in web worker using web assembly

我想在 Web Worker 中使用 WebAssembly。

在我的主应用程序中,我是这样启动它的:

let w = new Worker('test.js');
w.onmessage = (event) => { console.log(event); };
w.onerror = (event) => { console.error(event); };
w.postMessage({ message: "Hello World" });

然后,我创建了一个文件test.js如下:

self.Module = {
    locateFile: function (s) {
        console.log(s);
        return s;
    }
};

self.importScripts("main.js"); 
// note: `main.js` is the JavaScript glue file created by emcc

self.onmessage = function(messageEvent) {
    console.log(messageEvent); // works!
    console.log(self.Module); // works!
    console.log(self.Module.ccall("test")); // crashes!
}

我收到一个错误:Uncaught TypeError: Cannot read property 'apply' of undefined。我不明白为什么 self.Module 未定义,这怎么可能?

我感觉 Web Worker 和 WebAssembly 的范围有些地方不能很好地协同工作。

感谢您的意见!

问题在于 console.log() 不会在执行时揭示对象的真实状态。进一步挖掘表明,实际上对象 Module 还没有准备好。

我引用自:https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html

How can I tell when the page is fully loaded and it is safe to call compiled functions?

Calling a compiled function before a page has fully loaded can result in an error, if the function relies on files that may not be present

[...]

Another option is to define an onRuntimeInitialized function: Module['onRuntimeInitialized'] = function() { ... };

That method will be called when the runtime is ready and it is ok for you to call compiled code.

调整我的 test.js(工作人员)文件解决了这个问题:

self.Module = {
    locateFile: function (s) {
        console.log(s);
        return s;
    }
    // Add this function
    onRuntimeInitialized: function() {
        test();
    }
};

self.importScripts("main.js"); 
// note: `main.js` is the JavaScript glue file created by emcc

self.data = {};

// to pass data from the main JS file
self.onmessage = function(messageEvent) {
    console.log(messageEvent); // works!
    self.data = messageEvent; // save the data
}

// gets executed when everything is ready.
self.test = function() {
    // we may safely use self.data and self.Module now!
    console.log(self.Module.ccall("test")); // works!
}