Lui*_*ipe 4 javascript loops promise
假设我有以下for循环,这显然会阻塞事件循环一段时间:
function somethingExpensive() {
let i = 0;
while (true) {
// Something expensive...
if (++i === 1e10) return 'Some value.'
}
}
Run Code Online (Sandbox Code Playgroud)
我可以将该操作(for循环)包装在一个 Promise 中,这样它就不会阻塞“主线程”吗?
类似的东西:
function somethingExpensive() {
return new Promise((resolve) => {
let i = 0;
while (true) {
// Something expensive...
if (++i === 1e10) resolve('Some value.');
}
});
}
Run Code Online (Sandbox Code Playgroud)
只是在有限的范围内。如果昂贵的操作发生在同一个 Javascript 环境中,那么该环境的资源将被昂贵的操作占用,无论该昂贵的操作是同步发生还是异步发生(如 a 之后Promise.resolve)。例如,当操作正在进行时,用户可能无法与页面交互。
改用 Service Worker,这样昂贵的操作就可以在完全独立的环境中进行,从而可以正常地与原始页面进行交互。例如:
const workerFn = () => {
// something expensive
while (true) {
}
};
const workerFnStr = `(${workerFn})();`;
const blob = new Blob([workerFnStr], { type: 'text/javascript' });
const worker = new Worker(window.URL.createObjectURL(blob));
button.onclick = () => console.log('clicked');Run Code Online (Sandbox Code Playgroud)
body {
height: 1000px;
}Run Code Online (Sandbox Code Playgroud)
<button id="button">click</button>Run Code Online (Sandbox Code Playgroud)
那里的工作人员将消耗大量资源,但原始窗口将根据需要保持可滚动和可交互。如果没有工作人员,您将不得不忍受在昂贵的操作进行时原始窗口没有响应,或者将昂贵的操作错开到多个便宜的块中,例如,每 100 毫秒调用一次。(不过,即使使用这种方法,窗口也可能不会像人们希望的那样响应 - 使用工人更好)