如何在循环中等待多个 WebWorker
How to wait for multiple WebWorkers in a loop
我对 JS 中的 Web Worker 有以下问题。我有一个重型应用程序在做一些模拟。代码在多个 Web Worker 中运行。
主线程是网页上的 运行。但如果有意义的话,也可以是 Web Worker。
示例:
var myWebWorkers = [];
function openWorker(workerCount){
for(var i = 0; i < workerCount; i++){
myWebWorkers[i] = new Worker('worker.js');
myWebWorkers[i].onmessage = function(e){
this.result = e.data;
this.isReady = true;
}
}
}
function setWorkerData(somedata){
// somedata.length is always a multiple of myWebWorkers.length
var elementCntPerWorker = somedata.length / myWebWorkers.length;
myWebWorkers.forEach(function(worker, index){
worker.isReady = false;
worker.postMessage(
somedata.slice(index * elementCntPerWorker,
(index + 1) * elementCntPerWorker - 1));
});
}
var somedata = [...];
openWorker(8);
for(var i = 0; i < 10000; i++){
setWorkerData(somedata);
waitUntilWorkersAreDoneButAllowBrowserToReact(myWebWorkers);
if(x % 100) updateSVGonWebPage
}
function waitUntilWorkersAreDoneButAllowBrowserToReact(){
/* wait for all myWebWorkers-onchange event, but
allow browser to react and don't block a full Web Worker
Following example is my intension. But will not work, because
events are not executed until code excution stops.
*/
somedata = [];
for(var i = 0; i < myWebWorkers.length; i++){
while(!myWebWorkers[i].isReady);
somedata = somedata.concat(myWebWorkers.result);
}
}
我真正需要的是 waitUntilWorkersAreDoneButAllowBrowserToReact
函数或概念来获得这个 运行。每个关于 Mutex、sleep 等的搜索都以以下句子结束:"JS is single threaded"、"This will only work if you are not in a loop"、"There is no reason to have a sleep function"。等等
即使将主要任务传递给另一个 Worker,我也遇到了问题,如果其他线程都准备好了,这个线程 100% 负责检查,这是浪费能源和处理能力。
我希望有一个像 myWebWorker.waitForReady() 这样的阻塞函数,这样事件仍然可以得到处理。这将使 javascript 更上一层楼。但可能是我错过了一个简单的概念,可以做到这一点。
谢谢!
I would love to have a blocking function like myWebWorker.waitForReady()
不,那不可能。您研究的所有陈述都是正确的,网络工作者保持异步并且只会通过消息进行通信。没有等待事件,甚至在工作线程上也没有。
您将需要为此使用承诺:
function createWorkers(workerCount, src) {
var workers = new Array(workerCount);
for (var i = 0; i < workerCount; i++) {
workers[i] = new Worker(src);
}
return workers;
}
function doWork(worker, data) {
return new Promise(function(resolve, reject) {
worker.onmessage = resolve;
worker.postMessage(data);
});
}
function doDistributedWork(workers, data) {
// data size is always a multiple of the number of workers
var elementsPerWorker = data.length / workers.length;
return Promise.all(workers.map(function(worker, index) {
var start = index * elementsPerWorker;
return doWork(worker, data.slice(start, start+elementsPerWorker));
}));
}
var myWebWorkers = createWorkers(8, 'worker.js');
var somedata = [...];
function step(i) {
if (i <= 0)
return Promise.resolve("done!");
return doDistributedWork(myWebWorkers, somedata)
.then(function(results) {
if (i % 100)
updateSVGonWebPage();
return step(i-1)
});
}
step(1000).then(console.log);
Promise.all
does the magic of waiting for concurrently running results, and the step
function does the asynchronous looping 使用递归方法。
我对 JS 中的 Web Worker 有以下问题。我有一个重型应用程序在做一些模拟。代码在多个 Web Worker 中运行。 主线程是网页上的 运行。但如果有意义的话,也可以是 Web Worker。
示例:
var myWebWorkers = [];
function openWorker(workerCount){
for(var i = 0; i < workerCount; i++){
myWebWorkers[i] = new Worker('worker.js');
myWebWorkers[i].onmessage = function(e){
this.result = e.data;
this.isReady = true;
}
}
}
function setWorkerData(somedata){
// somedata.length is always a multiple of myWebWorkers.length
var elementCntPerWorker = somedata.length / myWebWorkers.length;
myWebWorkers.forEach(function(worker, index){
worker.isReady = false;
worker.postMessage(
somedata.slice(index * elementCntPerWorker,
(index + 1) * elementCntPerWorker - 1));
});
}
var somedata = [...];
openWorker(8);
for(var i = 0; i < 10000; i++){
setWorkerData(somedata);
waitUntilWorkersAreDoneButAllowBrowserToReact(myWebWorkers);
if(x % 100) updateSVGonWebPage
}
function waitUntilWorkersAreDoneButAllowBrowserToReact(){
/* wait for all myWebWorkers-onchange event, but
allow browser to react and don't block a full Web Worker
Following example is my intension. But will not work, because
events are not executed until code excution stops.
*/
somedata = [];
for(var i = 0; i < myWebWorkers.length; i++){
while(!myWebWorkers[i].isReady);
somedata = somedata.concat(myWebWorkers.result);
}
}
我真正需要的是 waitUntilWorkersAreDoneButAllowBrowserToReact
函数或概念来获得这个 运行。每个关于 Mutex、sleep 等的搜索都以以下句子结束:"JS is single threaded"、"This will only work if you are not in a loop"、"There is no reason to have a sleep function"。等等
即使将主要任务传递给另一个 Worker,我也遇到了问题,如果其他线程都准备好了,这个线程 100% 负责检查,这是浪费能源和处理能力。
我希望有一个像 myWebWorker.waitForReady() 这样的阻塞函数,这样事件仍然可以得到处理。这将使 javascript 更上一层楼。但可能是我错过了一个简单的概念,可以做到这一点。
谢谢!
I would love to have a blocking function like myWebWorker.waitForReady()
不,那不可能。您研究的所有陈述都是正确的,网络工作者保持异步并且只会通过消息进行通信。没有等待事件,甚至在工作线程上也没有。
您将需要为此使用承诺:
function createWorkers(workerCount, src) {
var workers = new Array(workerCount);
for (var i = 0; i < workerCount; i++) {
workers[i] = new Worker(src);
}
return workers;
}
function doWork(worker, data) {
return new Promise(function(resolve, reject) {
worker.onmessage = resolve;
worker.postMessage(data);
});
}
function doDistributedWork(workers, data) {
// data size is always a multiple of the number of workers
var elementsPerWorker = data.length / workers.length;
return Promise.all(workers.map(function(worker, index) {
var start = index * elementsPerWorker;
return doWork(worker, data.slice(start, start+elementsPerWorker));
}));
}
var myWebWorkers = createWorkers(8, 'worker.js');
var somedata = [...];
function step(i) {
if (i <= 0)
return Promise.resolve("done!");
return doDistributedWork(myWebWorkers, somedata)
.then(function(results) {
if (i % 100)
updateSVGonWebPage();
return step(i-1)
});
}
step(1000).then(console.log);
Promise.all
does the magic of waiting for concurrently running results, and the step
function does the asynchronous looping 使用递归方法。