浏览器中的页面循环系统&宏任务微任务

页面循环系统

js是单线程的,事件循环是js实现异步的一种方法,是js的执行机制,是一个不断进行循环的机制,来寻找可以执行的任务来执行。页面循环系统是浏览器统一管理页面中任务的机制,浏览器执行的任务,分为宏任务和微任务,宏任务在宏任务队列里,常见的宏任务:包括整体代码script(同步宏任务)、 setTimeout、setInterval(异步宏任务)、I/O、UI 交互事件(优先级较高)、postMessage、MessageChannel、setImmediate(Node.js 环境)。微任务在微任务队列里,常见的微任务: Promise.then(),process.nextTick,ajax请求(异步微任务)。 微任务的执行时机:执行时机是在主函数执行结束之后、当前宏任务结束之前。每个宏任务都关联了一个微任务队列。async/await是微任务+协程来实现的。

第三版线程:在第二版的线程模型中,所有的任务都是来自于线程内部的,如果其它线程想让主线程执行一个任务,利用第二版的线程模型是无法做到的。线程间通信:添加消息队列渲染进程中所有运行在主线程上的任务都需要先添加到消息队列,然后事件循环系统再按照顺序执行消息队列中的任务。由于是多个线程操作同一个消息队列,所以在添加任务和取出任务时还会加上一个同步锁。
不过刚提到的线程仅限于同一个进程内的,不同进程的线程通信:如渲染进程专门有一个 IO 线程用来接收其他进程传进来的消息,接收到消息之后,会将这些消息组装成任务发送给渲染主线程,后续的步骤就和前面的“处理其他线程发送的任务”一样了(循环机制+事件+消息队列
当页面主线程执行完成之后,又该如何保证页面主线程能够安全退出呢?Chrome 是这样解决的,确定要退出当前页面时,页面主线程会设置一个退出标志的变量,在每次执行完一个任务时,判断是否有设置退出标志。
页面使用单线程的缺点
第一个问题是如何处理高优先级的任务,(如 DOM 发生变化,采用同步通知的方式,会影响当前任务的执行效率;如果采用异步方式,又会影响到监控的实时性。)(消息队列机制不是很灵活所以引入了微任务);
第二个是如何解决单个任务执行时长过久的问题(js回调、异步)。

宏任务与微任务:

这两篇文章力荐!!!!!
深入前端-彻底搞懂JS的运行机制
这一次彻底弄懂JavaScript执行机制
消息队列不能胜任部分领域的要求(如监听dom变化),而微任务可以在实时性和效率之间做一个有效的权衡。
微任务就是一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前。每个宏任务都关联了一个微任务队列。
举个例子更好理解:

        Promise.resolve().then(()=>{
            console.log('Promise1')
            setTimeout(()=>{
                console.log('setTimeout2')
            },0)
        })
        setTimeout(()=>{//
            console.log('setTimeout1')
            Promise.resolve().then(()=>{
                console.log('Promise2')
            })
        },0)
//微任务Promise1进微任务队列
//注册宏任务setTimeout1,进入宏任务队列
//先执行微任务Promise1,打印'Promise1',遇到宏任务setTimeout2,进入宏任务队列,此时队列前面是setTimeout1
//接着执行宏任务setTimeout1,打印‘setTimeout1',遇到微任务Promise2,进入微任务队列
//此时宏任务里剩一个setTimeout2,微任务队列里剩一个Promise2,先执行微任务,再执行宏任务。
//Promise1 setTimeout1 Promise2 setTimeout2
  • 微任务和宏任务是绑定的,每个宏任务在执行时,会创建自己的微任务队列。
  • 微任务的执行时长会影响到当前宏任务的时长。比如一个宏任务在执行过程中,产生了 100 个微任务,执行每个微任务的时间是 10 毫秒,那么执行这 100 个微任务的时间就是 1000 毫秒,也可以说这 100个微任务让宏任务的执行时间延长了 1000 毫秒。
  • 在一个宏任务中,分别创建一个用于回调的宏任务和微任务,无论什么情况下,微任务都早于宏任务执行。

setTimeout和XMLHttpRequest是两个浏览器内置的WebAPI:

setTimeout
js——setTimeout和setInterval
XMLHtttpRequest
js_Ajax

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript 是一门单线程语言,也就是说在同一时间内只能执行一个任务。但是它又需要处理各种不同的任务,如 UI 事件、网络请求等。为了解决这个问题,JavaScript 引入了事件循环机制。 事件循环机制基于一个事件循环线程,该线程会不断地从任务队列取出任务并执行。任务可以分为两种类型:宏任务微任务宏任务是指由浏览器或 Node.js 提供的 API,如 setTimeout、setInterval、I/O 操作等。当宏任务执行完毕后,事件循环线程会从宏任务队列取出一个新的宏任务继续执行,直到宏任务队列为空。 微任务是指由 Promise、MutationObserver 等提供的异步任务。当一个微任务被加入队列时,事件循环线程会在当前宏任务执行完毕后,立即执行所有微任务。如果在执行微任务的过程,又产生了新的微任务,那么这些新的微任务会被添加到微任务队列的末尾,等待下一轮执行。 在事件循环机制,每个宏任务只会对应一个微任务队列。当一个宏任务执行完毕后,会依次执行该宏任务对应的微任务队列的所有微任务,直到微任务队列为空。然后再取出下一个宏任务并执行。 总结一下,事件循环机制的执行顺序为:执行一个宏任务,接着执行该宏任务微任务队列的所有微任务,然后再执行下一个宏任务。这个过程会不断地重复,直到所有任务都被执行完毕。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值