因此,我基本上是对数组中的对象执行很多操作。因此,我决定使用Webworkers,以便可以并行处理它们。但是,如果我输入包含10个对象的数组,则只有9个worker将返回一个值。因此,我创建了一个简单的模型来重现该问题:

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

最佳答案

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

发生这种情况是因为worker变量实际上是全局变量,而不是局部变量。您可以将var worker替换为let worker以使其成为局部变量。如果您担心let浏览器的兼容性,请使用Array来存储工作程序,或者只是创建一个函数作用域。

现在,在最后一个工作程序上调用终止,因为在循环结束时var 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/

09-17 15:04
查看更多