如何避免 JavaScript VM 被 CPU 绑定任务阻塞
How to avoid JavaScript VM to be blocked by CPU bound task
我在 JavaScript 中有一个 cpu 密集型任务,它在 Promise
:
中执行时阻塞了虚拟机
示例如下(在浏览器中尝试):
function task() {
return new Promise((r,s) => {
for(var x=0; x < 1000000*1000000; x++) {
var Y = Math.sqrt(x/2)
}
return r(true)
})
}
我想避免 VM 主线程被阻塞,所以我尝试在 Promise
中使用 setTimeout
传递 resolve
和 reject
作为上下文,如:
function task() {
return new Promise((r,s) => {
var self=this;
setTimeout( function(r,s) {
for(var x=0; x < 1000000*1000000; x++) {
var Y = Math.sqrt( Math.sin (x/2) + Math.cos(x/2))
}
return r(true);
},500,r,s);
})
}
但没有成功。知道如何避免主线程卡住吗?
您可以使用 "Web Workers"。这样,您就可以保持符合标准。这基本上是一个后台线程(例如旧 C# 中的 BackgroundWorker)。
我不确定当前 node.js 是否支持这个,所以使用
npm web workers package
除了使用 web worker 或类似工具之外,您还可以(根据任务)将工作分解为更小的块,这些块使用 setImmediate
进行处理和安排。这个例子有点傻,但你明白了。
function brokenUpTask() {
let x = 0; // Keep track of progress here, not in the loop.
const limit = 1000000;
const chunk = 100000;
return new Promise((resolve) => {
function tick() { // Work a single chunk.
let chunkLimit = Math.min(x + chunk, limit);
for(x = 0; x < chunkLimit; x++) {
var Y = Math.sqrt(x/2);
}
if(x === limit) { // All done?
resolve(true);
return;
}
setImmediate(tick); // Still work to do.
}
tick(); // Start work.
});
}
brokenUpTask().then(() => console.log('ok'));
我在 JavaScript 中有一个 cpu 密集型任务,它在 Promise
:
示例如下(在浏览器中尝试):
function task() {
return new Promise((r,s) => {
for(var x=0; x < 1000000*1000000; x++) {
var Y = Math.sqrt(x/2)
}
return r(true)
})
}
我想避免 VM 主线程被阻塞,所以我尝试在 Promise
中使用 setTimeout
传递 resolve
和 reject
作为上下文,如:
function task() {
return new Promise((r,s) => {
var self=this;
setTimeout( function(r,s) {
for(var x=0; x < 1000000*1000000; x++) {
var Y = Math.sqrt( Math.sin (x/2) + Math.cos(x/2))
}
return r(true);
},500,r,s);
})
}
但没有成功。知道如何避免主线程卡住吗?
您可以使用 "Web Workers"。这样,您就可以保持符合标准。这基本上是一个后台线程(例如旧 C# 中的 BackgroundWorker)。
我不确定当前 node.js 是否支持这个,所以使用 npm web workers package
除了使用 web worker 或类似工具之外,您还可以(根据任务)将工作分解为更小的块,这些块使用 setImmediate
进行处理和安排。这个例子有点傻,但你明白了。
function brokenUpTask() {
let x = 0; // Keep track of progress here, not in the loop.
const limit = 1000000;
const chunk = 100000;
return new Promise((resolve) => {
function tick() { // Work a single chunk.
let chunkLimit = Math.min(x + chunk, limit);
for(x = 0; x < chunkLimit; x++) {
var Y = Math.sqrt(x/2);
}
if(x === limit) { // All done?
resolve(true);
return;
}
setImmediate(tick); // Still work to do.
}
tick(); // Start work.
});
}
brokenUpTask().then(() => console.log('ok'));