我正在尝试编写一个可中断计算的Web Worker。 我所知道的唯一方法(除了Worker.terminate()
)是定期向消息循环屈服,以便它可以检查是否有任何新消息。 例如,此Web Worker计算从0到data
的整数之和,但如果您在计算正在进行时发送新消息,则会取消计算并启动一个新的计算。
let currentTask = {
cancelled: false,
}
onmessage = event => {
// Cancel the current task if there is one.
currentTask.cancelled = true;
// Make a new task (this takes advantage of objects being references in Javascript).
currentTask = {
cancelled: false,
};
performComputation(currentTask, event.data);
}
// Wait for setTimeout(0) to complete, so that the event loop can receive any pending messages.
function yieldToMacrotasks() {
return new Promise((resolve) => setTimeout(resolve));
}
async function performComputation(task, data) {
let total = 0;
while (data !== 0) {
// Do a little bit of computation.
total += data;
--data;
// Yield to the event loop.
await yieldToMacrotasks();
// Check if this task has been superceded by another one.
if (task.cancelled) {
return;
}
}
// Return the result.
postMessage(total);
}
这个方法可以运行,但速度非常慢。在我的机器上,while
循环的每个迭代平均需要4毫秒!如果你想快速实现取消操作,这是一个巨大的开销。
为什么会如此缓慢?有没有更快的方法来完成这项任务?
Promise.resolve
不起作用。 - CertainPerformance