事件执行顺序和渲染

var con = document.getElementById('con');

con.onclick = function () {

  Promise.resolve().then(function Promise1() {

    con.textContent = 0;

    // requestAnimationFrame(() => con.textContent = 0)

  });

};

<div id="con">this is con</div>

为什么这段代码在执行微任务后不触发渲染?


setTimeout(function setTimeout1() {

  console.log('setTimeout1')

}, 0)

var channel = new MessageChannel();

channel.port1.onmessage = function onmessage1() {

  console.log('postMessage');

  Promise.resolve().then(function promise1() {

    console.log('promise1');

  })

};

channel.port2.postMessage(0);

setTimeout(function setTimeout2() {

  console.log('setTimeout2')

}, 0);

console.log('sync');

为什么 postmessage 在 timer 之前执行?


白板的微信
浏览 75回答 1
1回答

30秒到达战场

为什么这段代码在执行微任务后不触发渲染?确实如此,否则您将看不到正在更新的文本...也许您无法从您的开发工具中分辨出来?这可能是因为鼠标事件现在通常被限制为屏幕刷新率,这意味着当调度鼠标事件的任务将运行时,您已经处于绘画框架中,这可能是出于其他原因(因为我知识,mousemove事件以这种方式受到限制,而不是单击...)。因此,您的Promise 回调将同步执行(只有第六步“将 currentTask 设置为 null”),在更新渲染步骤开始之前,所有开发工具都会看到一个正常的绘画框架,就像它在期待。所以也许,开发工具在这里不会显示任何特别的东西,但是鉴于您的主张的广泛性,很难确定一个特定的原因,这只是我的一个理论。您可以尝试通过requestAnimationFrame从此类事件内部调用来验证该理论,并检查它是否确实在同一事件循环迭代中执行:显示代码片段对我来说,它在 Chrome 中经常发生,在 Firefox 中只是偶尔出现一次,但同时我知道Chrome 的 rAF 被破坏了......所以这个理论非常薄弱。为什么 postmessage 在 timer 之前执行?这将取决于用户代理(浏览器)以及何时执行此代码以使该语句成立,当然也取决于它这样做的原因。在 Chrome中,他们为传递给的超时值设置了至少 1ms&nbsp;setTimeout:&nbsp;&nbsp;base::TimeDelta&nbsp;interval_milliseconds&nbsp;=&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;std::max(base::TimeDelta::FromMilliseconds(1),&nbsp;interval);消息任务没有超时,因此将立即排队。因此,如果没有其他任务要处理,它将是下一个执行的任务,早在 1ms 超时解决之前。在 Firefox中,他们将调度的任务setTimeout视为低优先级,当从页面加载开始调度时(这意味着在 Firefox 中setTimeout,如果两者都在页面加载之后调度,则消息任务实际上会在一个之后触发:显示代码片段)。因此,在这种页面加载的特殊情况下,他们将消息任务视为比超时任务更重要,并且任务执行者必须选择下一步执行哪个任务(作为事件第一步的一部分循环处理模型),它将在超时后选择消息。但这些都是实现的怪癖,规范中的任何内容都没有正式化这种行为。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript