为什么Web Worker不能直接调用函数?

Doz*_*zer 28 html5 web-worker

我们可以像HTML5一样使用HTML5中的web worker:

var worker = new Worker('worker.js');
Run Code Online (Sandbox Code Playgroud)

但为什么我们不能称这样的函数?

var worker = new Worker(function(){
    //do something
});
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 19

这是Web工作者的设计方式.它们必须有自己的外部JS文件和由该文件初始化的自己的环境.出于多线程冲突的原因,他们无法与常规的全局JS空间共享环境.

不允许Web工作者直接访问全局变量的一个原因是,它需要两个环境之间的线程同步,这不是可用的东西(并且会使事情变得非常复杂).当Web工作者拥有自己独立的全局变量时,除了通过与主JS线程正确同步的消息传递队列之外,他们不能搞乱主JS线程.

也许有一天,更高级的JS程序员将能够使用传统的线程同步技术来共享对公共变量的访问,但是现在两个线程之间的所有通信都必须通过消息队列,并且web worker无法访问主Javascript线程环境.


Rob*_*b W 10

之前已经问这个问题,但由于某种原因,OP决定删除它.
我重新发布我的答案,以防需要一个从函数创建Web worker的方法.


这篇文章中,显示了三种方法来从任意字符串创建Web工作者.在这个答案中,我使用的是第三种方法,因为它在所有环境中都受支持.

需要一个帮助文件:

// Worker-helper.js
self.onmessage = function(e) {
    self.onmessage = null; // Clean-up
    eval(e.data);
};
Run Code Online (Sandbox Code Playgroud)

在您的实际Worker中,此帮助程序文件的用法如下:

// Create a Web Worker from a function, which fully runs in the scope of a new
//    Worker
function spawnWorker(func) {
    // Stringify the code. Example:  (function(){/*logic*/}).call(self);
    var code = '(' + func + ').call(self);';
    var worker = new Worker('Worker-helper.js');
    // Initialise worker
    worker.postMessage(code);
    return worker;
}

var worker = spawnWorker(function() {
    // This function runs in the context of a separate Worker
    self.onmessage = function(e) {
        // Example: Throw any messages back
        self.postMessage(e.data);
    };
    // etc..
});
worker.onmessage = function() {
    // logic ...
};
worker.postMessage('Example');
Run Code Online (Sandbox Code Playgroud)

请注意,范围是严格分开的.变量只能通过传递来回回worker.postMessageworker.onmessage.所有消息都是结构化克隆.