等待几个 web worker 完成
Wait for several web workers to finish
我有一个创建多个网络工作者的脚本,这些网络工作者执行一些工作并在完成后发送消息。
问题是我需要从所有这些中得到结果,然后计算出最终的解决方案。在其他工作中,他们计算出问题的部分解决方案,主线程使用这些部分解决方案来生成最终答案。
我如何才能等待所有这些线程完成,Java脚本中是否有类似 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
的工作线程可能要到 i == 1
的工作线程 之后 才能完成,这只是因为线程调度的变幻莫测或工作需要更多处理。如果您按顺序需要它们,这很容易完成,但我们必须添加一个计数器(或在每次完成时循环 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,它是 JavaScript 自 ES2015(又名 ES6)起原生的,并且可以填充以用于较旧的 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
});
你可以承诺工人然后使用 Promise.all
:
Promise.all(Array.from(Array(100), (x, i) => i).map(i =>
new Promise((resolve, reject) => {
const worker = new Worker('js/worker.js');
worker.postMessage(i);
worker.addEventListener('message', event => resolve(event.data));
worker.addEventListener('error', reject);
}))
.then(results => ...);
我有一个创建多个网络工作者的脚本,这些网络工作者执行一些工作并在完成后发送消息。
问题是我需要从所有这些中得到结果,然后计算出最终的解决方案。在其他工作中,他们计算出问题的部分解决方案,主线程使用这些部分解决方案来生成最终答案。
我如何才能等待所有这些线程完成,Java脚本中是否有类似 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
的工作线程可能要到 i == 1
的工作线程 之后 才能完成,这只是因为线程调度的变幻莫测或工作需要更多处理。如果您按顺序需要它们,这很容易完成,但我们必须添加一个计数器(或在每次完成时循环 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,它是 JavaScript 自 ES2015(又名 ES6)起原生的,并且可以填充以用于较旧的 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
});
你可以承诺工人然后使用 Promise.all
:
Promise.all(Array.from(Array(100), (x, i) => i).map(i =>
new Promise((resolve, reject) => {
const worker = new Worker('js/worker.js');
worker.postMessage(i);
worker.addEventListener('message', event => resolve(event.data));
worker.addEventListener('error', reject);
}))
.then(results => ...);