创建了10个Web工作者,但只返回了9个值

时间:2017-06-28 12:50:36

标签: javascript web-worker

所以我基本上对数组中的对象进行了大量操作。所以我决定使用网络工作者,这样我就可以并行处理它们了。但是,如果我输入一个包含10个对象的数组,则只有9个工作符会返回一个值。所以我创建了这个简单的模型来重现问题:

var numbers = [12, 2, 6, 5, 5, 2, 9, 8, 1, 4];
var create = function(number) {
    var source = 'onmessage = function(e) { postMessage(e.data * 3) }';
    var blob = new Blob([source]);
    var url = window.URL.createObjectURL(blob);
    return new Worker(url)
}; 

var newnumbers = [];
for (var i = 0; i < numbers.length; i++) {
    var worker = create();
    worker.onmessage = function(e) {
        newnumbers.push(e.data);
        worker.terminate();
    }

    worker.postMessage(numbers[i]);
}

基本上,de数组中的每个数字都乘以3并添加到新数组newnumbers。但是,numbers.length = 10newnumbers.length=9。我已经调试了很长一段时间,我确认已经创建了10个工作人员。

我觉得我做了一些愚蠢的错事,但有人可以解释一下吗?

Run it here on JSFiddle

1 个答案:

答案 0 :(得分:1)

在处理消息之前,您在最后一个工作程序上调用terminate,因此最后一个工作程序没有输出任何内容。

这是因为worker变量实际上是全局变量而不是本地变量。您可以将var worker替换为let worker,使其成为本地变量。如果您担心let浏览器兼容性,请使用Array来存储工作人员,或者只创建一个函数范围。

现在,在最后一个worker上调用terminate,因为var worker变量将在循环结束时设置为最后一个worker。请注意,循环将在任何工作程序开始处理之前完成执行(因为循环是同步代码)。

在原始代码中,不要在每个工作人员上调用terminate(),而是在最后工作人员上调用10次terminate()

var newnumbers = [];
for (var i = 0; i < numbers.length; i++) {
    let worker = create();
    worker.onmessage = function(e) {
        newnumbers.push(e.data);
        worker.terminate(); // "worker" refers to the unique variable created each iteration
    }
    worker.postMessage(numbers[i]);
}

演示:https://jsfiddle.net/bqf5e9o1/2/