在通过setTimeout或promise阻止代码之前更新DOM [英] Updating DOM before blocking code by setTimeout or promise

查看:139
本文介绍了在通过setTimeout或promise阻止代码之前更新DOM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,如果有CPU密集型代码,则不会立即进行之前的DOM更新。例如

I know that when there is a CPU intensive code any immediate previous DOM update won't happen. Such as

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);

<p id="result"></p>

但是,如果我将CPU密集型代码通过 setTimeout 移到异步时间轴,则可以像下面的代码片段一样正常。

However if I shift the CPU intensive code to the asynchronous timeline by setTimeout it's all fine as in the following snippet.

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 side

<p id="result"></p>

但是因为我知道承诺也会带您进入某种非同步时间表,所以我希望在不使用 setTimeout hack的情况下达到相同的效果。例如;

However since i know that promises also take you to a "sort of" asycnronous timeline i was expecting to achieve the same effect without using the setTimeout hack. Such as;

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)

<p id="result"></p>

由于这篇完美的文章( https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ )没办法。

I would at least expect this to run as expected in FF because of this perfect article (https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) alas no way.

有没有办法用诺言来完成这项工作?

Is there any way to accomplish this job with promises?

推荐答案

Promise.prototype .then 具有 microtask 语义。这意味着它必须等待同步代码运行,而不必等待异步代码运行-浏览器可能选择在进行DOM更新之前等待所有JS运行。

Promise.prototype.then has microtask semantics. This means it has to wait for synchronous code to run but not for asynchronous code to run - browsers probably choose to wait for all JS to run before doing DOM updates.

通常 microtask 意味着它必须等待其他JS运行,然后才能运行之前将控制权交给非JS代码。

Generally microtask means it has to wait for other JS to run, and then it can run before yielding control to non JS code.

setTimeout 具有宏任务语义。它运行作为DOM API的一部分,并且当回调运行时,非js代码已经有运行的机会。浏览器在运行时已经运行了自己的代码,因此它们也可以处理事件和DOM更新。

setTimeout has macrotask semantics. It runs as a part of the DOM API and when the callback runs the non-js code has already gotten a chance to run. Browsers already run their own code when this runs so they also process events and DOM updates.

通常宏任务意味着必须等待所有代码其他JS要运行,也用于事件循环以打勾-即:要触发的事件。

Generally macrotask means that it has to wait for all other JS to run and also for the "event loop to tick" - that is: events to fire.

这也是 NodeJS中的 setImmediate nextTick 之间的区别

This is also the difference between setImmediate and nextTick in NodeJS.

直接回答您的问题:否。无法强制浏览器在microtick更新中运行DOM更新-虽然从技术上来讲,它不是禁止这样做的方式-这将是举止不好。

To answer your question directly: no. There is no way to force the browser to run DOM updates in a microtick update - while it is technically not forbidden for it to do so - it would be "bad mannered".

对于长时间运行的CPU绑定操作-我建议 Web Workers 代替?

For long running CPU bound operations - may I suggest Web Workers instead?

这篇关于在通过setTimeout或promise阻止代码之前更新DOM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆