将 require.js 与网络工作者一起使用的正确方法是什么?

What's the right way to use require.js with web-workers?

目前,我正在努力将现有的网络应用程序移植到 require.js。大多数事情似乎都有效,但使用网络工作者的功能。例如,我有一个在单独的 js 文件 MeshLoader.js 中定义的工作人员,它从 STL 文件加载 3D 模型:

importScripts('../lib/three.min.js', '../lib/STLLoader.js');

onmessage = function(e) {
    var blob = e.data;
    var reader = new FileReaderSync();
    readContents(reader.readAsArrayBuffer(blob));
};

function readContents(contents) {
    try {
        var geometry = new THREE.STLLoader().parse(contents);
    } catch (e) {
        // error handling
    }

    var attributes = {};
    // parsing the file is going on here
    // ...

    postMessage({
            status: 'completed',
            attributes: attributes,
    });
}

小提示:STLLoader.js 模块是一个 three.js 插件,它定义 STLLoader 对象并将其添加到 THREE 命名空间。这就是我用 require.js:

重写它的方式
importScripts('../lib/require.min.js');

require({
    baseUrl: '../lib'
}, [
    'require', 'three.min', 'stlloader'
],
function(require, THREE, STLLoader) {
    onmessage = function(e) {
        var blob = e.data;
        var reader = new FileReaderSync();
        readContents(reader.readAsArrayBuffer(blob));
    };

    function readContents(contents) {
        try {
            var geometry = new THREE.STLLoader().parse(contents);
        } catch (e) {
            // error handling
        }

        var attributes = {};
        // same code as in the initial version
        // ...

        postMessage({
            status: 'completed',
            attributes: attributes,
        });
    }

    return onmessage;
});

工人的调用方式如下:

var worker = new Worker('js/workers/MeshLoader.js');
worker.postMessage(blob);
worker.onmessage = function (event) {
    if (event.data.status == 'completed') {
        // ...
    } else if (event.data.status == 'failed') {
       // ...
    } else if (event.data.status == 'working') {
       // ...
    }
};

所以,问题是似乎根本没有调用工人。也许我需要在 requirejs.config() 部分将其声明为一个模块,然后将该模块作为依赖项添加到调用此 worker 的其他模块?

我是这样用的(jsfiddle):

importScripts("require.js");
requirejs.config({
    //Lib path
    baseUrl: '.',
    // Some specific paths or alternative CDN's
    paths: {
        "socket.io": [
            "//cdn.socket.io/socket.io-1.3.7",
            "socket.io.backup"]
    },
    waitSeconds: 20
});


requirejs(["LibName"], (TheLibrary) = > {
  // code after all is loaded
  self.onmessage = (msg)=>{
    // do stuff
    TheLibrary.doStuff(msg.data);
  }
  // I tend to dispatch some message here
  self.postMessage("worker_loaded");
}

请注意,只有在您收到 "worker_loaded" 后,您才能 post 向工作人员发送消息,因为只有这样消息才会被接受。之前,onmessage回调还没有建立。所以你的主要代码应该是:

var worker = new Worker("myworker.js");
worker.onmessage = function(e) {
  if(e.data=="worker_loaded") { 
    // Tell worker to do some stuff
  }
}