当前位置: 首页 > Web前端 > HTML

在浏览器事件循环中关注我

时间:2023-03-28 17:13:55 HTML

1。什么是浏览器事件循环?我们知道在javascript中,有定时器setTimeout,服务请求ajax,ui渲染,还有一些Promise等等,浏览器在解析这些代码的时候,并不是同步的。比如setTimeout等到时间到了才会执行,ajax等到服务器响应后才会拿到返回的数据。那么浏览器怎么知道什么时候处理setTimeout或者ajax呢?方法是循环往复,形成浏览器事件循环。2、宏任务和微任务先了解这两个概念宏任务:ajax、setTimeout、setInterval、I/O、event微任务:Promise、process。一张图就足以说明,所有的js代码都是先执行,遇到宏任务和微任务就交给对应的线程,各自在自己的线程中执行ajax、setTimeout、Promise等异步操作,比如setTimeout是在自己的线程中执行的,当时间到了,回调会放到宏任务队列中;同样的,Promise等到那个时候,回调会被放到微任务队列中。第一步js代码全部执行完后,会先清空所有microtasks。第三步清空所有microtask队列的时候,这个时候也可能会遇到microtasks或者macrotasks,同理。此时将遇到的microtasks添加到microtasks的末尾。这次清空微任务队列的过程中,添加的也会清空,宏任务会加入到宏任务队列中。然后进行一次ui渲染,从宏任务队列中取出第一个执行(每个循环只执行一个宏任务,微任务全部执行)。执行宏任务代码时,也有可能再次遇到宏任务和微任务。当任务执行时,再次将它们添加到相应的任务队列中。task执行完后,再次取出microtask队列执行,再次清空microtask。渲染页面并从宏任务队列中取出一个宏任务再次执行,如此反复直到任务队列清空。记住每个循环的几个点,所有microtask都清零,只执行一个macrotask。microtask清空后就是Performuirendering4.事件环实战document.body.style.background='red';console.log(1)Promise.resolve().then(()=>{console.log(2)document.body.style.background='green';})console.log(3);printresults132另外:在页面中,看不到红色view,只有绿色。因为先执行微任务,然后再进行ui渲染。执行微任务时,body的背景设置为绿色,红色被覆盖,创建一个复杂的例子。setTimeout(()=>{console.log(1);Promise.resolve().then(()=>{console.log(2);});},0);newPromise((resolve)=>{console.log(3);resolve();}).then(()=>{console.log(4);});Promise.resolve().then(()=>{console.log(5);}).then(()=>{console.log(6);setTimeout(()=>{console.log(7);},1000);}).then(()=>{console.日志(8);});printresult34568127原因:遇到setTimeout交给setTimeout线程执行时,定时器为0秒。线程立即将回调放入宏任务队列,遇到新的Promise。请注意,新Promise的回调会立即执行。先打印出3,然后把then放到microtask队列中,遇到Promise.resolve时,把5放到microtask队列中。主代码执行完毕后,再清空微任务队列中的微任务。第一个放入的是4,第二个打印出来的microtask是5,打印出5,执行5的时候,再次遇到microtask6,加入tail队列,然后执行6microtask,打印出6microtask6的时候执行,遇到setTimeout,交给setTimeout线程处理,setTimeout线程会在1秒后将回调放入macrotask队列。微任务6被执行。当遇到microtask8时,同样会清除8。打印8.此时清除了microtask,执行了一个macrotask。,打印1macrotask1执行时,遇到microtask2,加入microtask队列然后清空所有microtasks,打印2setTimeoutthread1秒后,将7加入macrotask队列,最后打印7