Red*_*edu 5 javascript asynchronous settimeout promise es6-promise
我知道,当存在 CPU 密集型代码时,任何先前的 DOM 更新都不会发生。例如
function blockFor(dur){
var now = new Date().getTime();
while (new Date().getTime() < now + dur);
result.textContent = "I am done..!";
}
result.textContent = "Please remain..."; // we will never see this
blockFor(2000);Run Code Online (Sandbox Code Playgroud)
<p id="result"></p>Run Code Online (Sandbox Code Playgroud)
但是,如果我将 CPU 密集型代码转移到异步时间线,那么setTimeout一切都很好,如以下代码片段所示。
function blockFor(dur){
var now = new Date().getTime();
while (new Date().getTime() < now + dur);
result.textContent = "I am done..!";
}
result.textContent = "Please remain..."; // now you see me
setTimeout(_ => blockFor(2000),15); // 15ms to be on the safe sideRun Code Online (Sandbox Code Playgroud)
<p id="result"></p>Run Code Online (Sandbox Code Playgroud)
然而,因为我知道承诺也会带你进入“某种”异步时间线,所以我希望在不使用setTimeout黑客的情况下达到相同的效果。例如;
function blockFor(dur){
var now = new Date().getTime();
while (new Date().getTime() < now + dur);
result.textContent = "I am done..!";
}
result.textContent = "Please remain..."; // not in Chrome not in FF
Promise.resolve(2000)
.then(blockFor)Run Code Online (Sandbox Code Playgroud)
<p id="result"></p>Run Code Online (Sandbox Code Playgroud)
我至少希望它能在 FF 中按预期运行,因为这篇完美的文章(https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)可惜没办法。
有什么办法可以用承诺来完成这项工作吗?
Promise.prototype.then具有微任务语义。这意味着它必须等待同步代码运行,而不是异步代码运行——浏览器可能选择等待所有 JS 运行后再进行 DOM 更新。
一般来说,微任务意味着它必须等待其他 JS 运行,然后才能运行,然后才将控制权交给非 JS 代码。
setTimeout具有宏任务语义。它作为 DOM API 的一部分运行,当回调运行时,非 js 代码已经有机会运行。当它运行时,浏览器已经运行了自己的代码,因此它们也处理事件和 DOM 更新。
一般来说,macrotask意味着它必须等待所有其他 JS 运行以及“事件循环滴答”——即:事件触发。
这也是NodeJS和之间的区别setImmediatenextTick。
直接回答你的问题:不。没有办法强制浏览器在 microtick 更新中运行 DOM 更新——虽然技术上并没有禁止这样做——但这将是“不礼貌的”。
对于长时间运行的 CPU 密集型操作 - 我可以建议使用Web Workers吗?