javascript - 等待几个 web worker 完成

标签 javascript web-worker

我有一个创建多个网络 worker 的脚本,这些网络 worker 执行一些工作并在完成时发送消息。

问题是我需要从所有这些中得到结果,然后计算出最终的解决方案。在其他工作中,他们计算出问题的部分解决方案,主线程使用这些部分解决方案来生成最终答案。

我如何才能等待所有这些线程完成,Javascript 中是否有类似 Java 中的 invokeAll 的东西?

或多或少,我的主线程中有:

var data = [];

function createWorker(i) {
    var v = new Worker('js/worker.js');
    v.postMessage(i);
    v.onmessage = function(event){
        data.push(event.data);
    };
}

for(var i = 0; i < 100; i++) {
    createWorker(i);
}

//Wait until all have finished somehow

最佳答案

当收到最后一条数据时,调用您的计算最终解决方案函数:

var data = [];

function createWorker(i) {
    var v = new Worker('js/worker.js');
    v.postMessage(i);
    v.onmessage = function(event){
        data.push(event.data);
        if (data.length === 100) {               // <====
            computeFinalSolution();              // <====
        }                                        // <====
    };
}

for(var i = 0; i < 100; i++) {
    createWorker(i);
}

显然,在您认为必要时对其进行参数化,但是 createWorker 目前除了 i 之外未进行参数化,所以...

请注意,data 中的条目可能没有按顺序排列。 i == 0 的 worker 可能要等到 i == 1 的 worker 后才能完成,这只是因为线程调度的变幻莫测或如果工作需要更多处理。如果您按顺序需要它们,这很容易完成,但我们必须添加一个计数器(或在每次完成时循环遍历 data 进行检查):

var data = [];
var dataReceived = 0;

function createWorker(i) {
    var v = new Worker('js/worker.js');
    v.postMessage(i);
    v.onmessage = function(event){
        data[i] = event.data;                    // <====
        if (++dataReceived === 100) {            // <====
            computeFinalSolution();              // <====
        }                                        // <====
    };
}

for(var i = 0; i < 100; i++) {
    createWorker(i);
}

如果您想要一种更现代、更灵活的方法,请考虑使用 promises,它是 ES2015(又名 ES6)原生的 JavaScript,并且可以填充以用于旧的 JavaScript 引擎:

function createWorker(i) {
    return new Promise(function(resolve) {
        var v = new Worker('js/worker.js');
        v.postMessage(i);
        v.onmessage = function(event){
            resolve(event.data);
        };
    });
}

var promises = [];
for(var i = 0; i < 100; i++) {
    promises.push(createWorker(i));
}
Promise.all(promises)
    .then(function(data) {
        // `data` has the results, compute the final solution
    });

这还有一个好处,即 data按顺序包含结果,我们不必自己做这项工作。

以上内容与您当前的代码一致,该代码似乎没有任何错误规定。但通常最好进行错误处理:

function createWorker(i) {
    return new Promise(function(resolve, reject) {
        var v = new Worker('js/worker.js');
        v.postMessage(i);
        v.onmessage = function(event){
            // If you report errors via messages, you'd have a branch here for checking
            // for an error and either calling `reject` or `resolve` as appropriate.
            resolve(event.data);
        };
        // EITHER:
        v.onerror = reject; // Rejects the promise if an error is raised by the web worker, passing along the ErrorEvent
        // OR:
        v.onerror = function(event) {
            // Rejects the promise using the error associated with the ErrorEvent
            reject(event.error);
        };
    });
}

var promises = [];
for(var i = 0; i < 100; i++) {
    promises.push(createWorker(i));
}
Promise.all(promises)
    .then(function(data) {
        // `data` has the results, compute the final solution
    })
    .catch(function(error) {
        // something went wrong
    });

关于javascript - 等待几个 web worker 完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41423905/

相关文章:

javascript - 工作人员在 Chrome 中阻塞 UI 线程

javascript - Node.js 有一个好的索引/搜索引擎吗?

javascript - 繁重的计算和数据显示而不阻塞UI

javascript - webpack 2 将 webworker 公开为全局

javascript - 如何在 NextJS 10 中初始化 webworker?

javascript - 没有单独的 Javascript 文件的网络 worker ?

javascript - React/Redux 开发应该是面向对象编程还是函数式编程?

javascript - 保存不保存任何数据

javascript - 子字符串索引问题

javascript - 后退按钮上的 jQuery 动画