Javascript 如何使webworker的onmessage阶段异步?
我正在使用webworker计算属于这些位置的坐标和值。计算完全在后台进行,保持DOM的响应性。但是,当我将数据从webworker发送回主线程时,DOM会在一部分传输时间内没有响应 我的网络工作者(发送部分):Javascript 如何使webworker的onmessage阶段异步?,javascript,asynchronous,web-worker,Javascript,Asynchronous,Web Worker,我正在使用webworker计算属于这些位置的坐标和值。计算完全在后台进行,保持DOM的响应性。但是,当我将数据从webworker发送回主线程时,DOM会在一部分传输时间内没有响应 我的网络工作者(发送部分): //calculates happen before; this is the final step to give the calculated data back to the mainthread. var processProgressGEO = {'cmd':'geoRepo
//calculates happen before; this is the final step to give the calculated data back to the mainthread.
var processProgressGEO = {'cmd':'geoReport', 'name': 'starting transfer to main', 'current': c, 'total': polys}
postMessage(processProgressGEO);
postMessage({
'cmd':'heatmapCompleted',
'heatdata': rehashedMap,
'heatdatacount': p,
'current': c,
'total': polys,
'heatmapPeak': peakHM,
});
self.close();
var heatMaxforAuto = 1000000; //maximum amount of datapoints allowed in the texdata. This takes into account the spread of a singel datapoint.
async function fetchHeatData(){
return new Promise((resolve, reject) => {
var numbercruncher = new Worker('calculator.js');
console.log("Performing Second XHR request:");
var url2 = 'backend.php?datarequest=geodata'
$.ajax({
type: "GET",
url: url2,
}).then(async function(RAWGEOdata) {
data.georaw = RAWGEOdata;
numbercruncher.onmessage = async function(e){
var w = (e.data.current/e.data.total)*100+'%';
if (e.data.cmd === 'geoReport'){
console.log("HEAT: ", e.data.name, end(),'Sec.' );
}else if (e.data.cmd === 'heatmapCompleted') {
console.log("received Full heatmap data: "+end());
data.heatmap = e.data.heatdata;
console.log("heatData transfered", end());
data.heatmapMaxValue = e.data.heatmapPeak;
data.pointsInHeatmap = e.data.heatdatacount;
console.log("killing worker");
numbercruncher.terminate();
resolve(1);
}else{
throw "Unexpected command received by worker: "+ e.data.cmd;
}
}
console.log('send to worker')
numbercruncher.postMessage({'mode':'geo', 'data':data});
}).catch(function(error) {
reject(0);
throw error;
})
});
}
async function makemap(){
let heatDone = false;
if (data.texdatapoints<= heatMaxforAuto){
heatDone = await fetchHeatData();
}else{
var manualHeatMapFetcher = document.createElement("BUTTON");
var manualHeatMapFetcherText = document.createTextNode('Fetch records');
manualHeatMapFetcher.appendChild(manualHeatMapFetcherText);
manualHeatMapFetcher.id='manualHeatTriggerButton';
manualHeatMapFetcher.addEventListener("click", async function(){
$(this).toggleClass('hidden');
heatDone = await fetchHeatData();
console.log(heatDone, 'allIsDone', end());
});
document.getElementById("toggleIDheatmap").appendChild(manualHeatMapFetcher);
}
}
makemap();
HEAT: starting transfer to main 35 Sec. animator.js:44:19
received Full heatmap data: 51 animator.js:47:19
heatData transfered 51 animator.js:49:19
killing worker animator.js:52:19
1 allIsDone 51
上面代码段中的变量rehashedMap
是一个带有数字键的对象。每个键都包含一个数组
,其中包含另一个对象
我的主线程(仅相关部分:)
问题:
我的DOM在数据传输开始和收到完整热图数据后的消息之间冻结。这是我的控制台中第一条和第二条消息之间的阶段。传输需要16秒,但DOM在这段时间内只有一次没有响应。Webworkers无法与主线程共享数据,因此需要进行传输
问题:
首先,如何防止在webworker的onmessage
阶段冻结DOM?第二,更出于好奇:这种冻结怎么可能只发生在该阶段的一部分,因为它们是由两个连续步骤触发的,而中间没有发生任何事情
到目前为止我所尝试的:
//calculates happen before; this is the final step to give the calculated data back to the mainthread.
var processProgressGEO = {'cmd':'geoReport', 'name': 'starting transfer to main', 'current': c, 'total': polys}
postMessage(processProgressGEO);
postMessage({
'cmd':'heatmapCompleted',
'heatdata': rehashedMap,
'heatdatacount': p,
'current': c,
'total': polys,
'heatmapPeak': peakHM,
});
self.close();
var heatMaxforAuto = 1000000; //maximum amount of datapoints allowed in the texdata. This takes into account the spread of a singel datapoint.
async function fetchHeatData(){
return new Promise((resolve, reject) => {
var numbercruncher = new Worker('calculator.js');
console.log("Performing Second XHR request:");
var url2 = 'backend.php?datarequest=geodata'
$.ajax({
type: "GET",
url: url2,
}).then(async function(RAWGEOdata) {
data.georaw = RAWGEOdata;
numbercruncher.onmessage = async function(e){
var w = (e.data.current/e.data.total)*100+'%';
if (e.data.cmd === 'geoReport'){
console.log("HEAT: ", e.data.name, end(),'Sec.' );
}else if (e.data.cmd === 'heatmapCompleted') {
console.log("received Full heatmap data: "+end());
data.heatmap = e.data.heatdata;
console.log("heatData transfered", end());
data.heatmapMaxValue = e.data.heatmapPeak;
data.pointsInHeatmap = e.data.heatdatacount;
console.log("killing worker");
numbercruncher.terminate();
resolve(1);
}else{
throw "Unexpected command received by worker: "+ e.data.cmd;
}
}
console.log('send to worker')
numbercruncher.postMessage({'mode':'geo', 'data':data});
}).catch(function(error) {
reject(0);
throw error;
})
});
}
async function makemap(){
let heatDone = false;
if (data.texdatapoints<= heatMaxforAuto){
heatDone = await fetchHeatData();
}else{
var manualHeatMapFetcher = document.createElement("BUTTON");
var manualHeatMapFetcherText = document.createTextNode('Fetch records');
manualHeatMapFetcher.appendChild(manualHeatMapFetcherText);
manualHeatMapFetcher.id='manualHeatTriggerButton';
manualHeatMapFetcher.addEventListener("click", async function(){
$(this).toggleClass('hidden');
heatDone = await fetchHeatData();
console.log(heatDone, 'allIsDone', end());
});
document.getElementById("toggleIDheatmap").appendChild(manualHeatMapFetcher);
}
}
makemap();
HEAT: starting transfer to main 35 Sec. animator.js:44:19
received Full heatmap data: 51 animator.js:47:19
heatData transfered 51 animator.js:49:19
killing worker animator.js:52:19
1 allIsDone 51
onmessage
阶段的方法;但是,与postMessage
阶段()相比,文档()中没有指定此类选项。我是不是遗漏了什么setTimeout(fn,0)
(可能与requestAnimationFrame
结合使用,以确保重新绘制已发生)在短暂地向浏览器屈服后安排继续工作(使用fn
)
Int32Array
)使用的内存是可转移的
const workerCode=document.getElementById(“worker”).textContent;
constworkerblob=newblob([workerCode],{type:“text/javascript”});
常量workerUrl=(window.webkitURL | | window.URL).createObjectURL(workerBlob);
const worker=新的worker(workerUrl);
worker.addEventListener(“消息”,({data})=>{
if((数据和数据操作)=“数据”){
log(Date.now(),`Received${data.array.length}rows`);
如果(data.done){
停止旋转();
}
}
});
document.getElementById(“btn go”).addEventListener(“单击”,()=>{
log(Date.now(),“请求数据”);
startSpinning();
worker.postMessage({action:“go”});
});
常量微调器=document.getElementById(“微调器”);
常数状态=[…”▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"];
设stateIndex=0;
设spinHandle=0;
设maxDelay=0;
设intervalStart=0;
函数startSpinning(){
if(微调器){
取消动画帧(spinHandle);
maxDelay=0;
队列更新();
}
}
函数queueUpdate(){
间隔星