Javascript 为什么嵌套的postMessage会导致rAF在setTimeout之前被触发?

Javascript 为什么嵌套的postMessage会导致rAF在setTimeout之前被触发?,javascript,html,frontend,es6-promise,Javascript,Html,Frontend,Es6 Promise,代码: var mc=newmessagechannel(); var计数=1; var t=+新日期; console.log('start') Promise.resolve()。然后(()=>console.log('Promise')) requestAnimationFrame(()=>console.log('animationframe')) setTimeout(()=>console.log('timeout')) mc.port1.onmessage=(…arr)=>{ c

代码:

var mc=newmessagechannel();
var计数=1;
var t=+新日期;
console.log('start')
Promise.resolve()。然后(()=>console.log('Promise'))
requestAnimationFrame(()=>console.log('animationframe'))
setTimeout(()=>console.log('timeout'))
mc.port1.onmessage=(…arr)=>{
console.log('ommessage')
//这将导致在**rAF之前**触发setTimeout
if(count==1){mc.port2.postMessage(null);count=2}
//我想可能是因为我们花了太多的时间,所以皇家空军被改变了?但那不是真的,因为如果我删除上面的代码,使用下面的代码,就不会发生这种情况
//而(+新日期-t<3000){}
//或
//Promise.resolve().然后(()=>while(+new Date-t<3000))
}
mc.port2.postMessage(null);

console.log('end')
这里似乎对
requestAnimationFrame
的功能以及所有这些事件的发生方式有一些误解

因此,首先,
requestAnimationFrame(callback)
callback
存储在。此映射将被清空,并在下一步(步骤10)调用其所有回调。
这个绘制框架是HTML规范没有明确定义何时应该故意绘制的,实现者确实根据他们自己的启发来决定何时最好绘制。例如,Firefox会每隔60秒调用一次,而Chrome则会以与显示页面的显示器相同的速率调用

因此,如果我们从外部观察,我们可以说,
requestAnimationFrame
只是一个
setTimeout(回调,直到下一个画框的时间)

但是,这些回调都将在接近事件循环结束时被调用

另一方面,事件将在事件循环的开始处处理。特别是消息事件是触发算法的最快方式,因为它是最简单的。
而计时器将始终在以后至少触发两次事件循环迭代:

  • 声明计时器
  • 如果时间已过,请排队等待任务
  • 触发任务
  • 这就是为什么
    onmessage
    应该在超时之前触发的原因(尽管从技术上讲,延迟超时可能在
    onmessage
    之前触发)

    现在我们来看看
    Promise.resolve()
    创建的最后一个beast,microtasks。它们只等待当前任务的当前执行。也就是说,回调、事件处理程序或内联脚本调用了Promise的
    resolve
    方法,或者进行了触发MutationObserver事件的更改

    也许就这一点而言,一个简单的例子胜过千言万语:

    const channel=new MessageChannel();
    channel.port1.onmessage=({data})=>{
    log(`enter message${data}事件处理程序`);
    承诺,决心
    .然后(()=>{
    log(`enter microtask${data}事件处理程序`);
    承诺,决心
    .然后(()=>
    log(`enter sub microtask${data}事件处理程序`)
    )
    //我们可以在这里进入一个无限循环
    //这就像一个while循环一样阻塞
    //因为我们从不离开当前的任务
    } )
    };
    //两个事件都应该发生在同一个事件循环迭代中
    通道端口2.后消息(1);
    
    channel.port2.postMessage(2)不太清楚您试图做什么。可以看到rAF自己工作。rAF在下一个勾号(setTimeout)之前触发,但在这里它在下一个勾号(setTimeout)之后触发,但是没有任何操作会导致丢弃帧,只有一条postMessage