浏览器的页面循环系统

156 阅读3分钟

消息队列和事件循环

  • 浏览器页面是由消息队列和事件循环系统来驱动的
  • 消息队列是一种数据结构,可以存放要执行的任务,它符合队列“先进先出”

2.png

setTimeout实现

  • 为了支持定时器的实现,浏览器增加了延时队列

  • 由于消息队列排队和一些系统级别的限制,通过 setTimeout 设置的回调任务并非总是可以实时地被执行,这样就不能满足一些实时性要求较高的需求了

  • 使用 setTimeout 的一些注意事项

    1、如果当前任务执行时间过久,会影延迟到期定时器任务的执行

    2、如果 setTimeout 存在嵌套调用,那么系统会设置最短时间间隔为 4 毫秒

    3、未激活的页面,setTimeout 执行最小间隔是 1000 毫秒

    4、延时执行时间有最大值【Chrome、Safari、Firefox 都是以 32 个 bit 来存储延时值的,32bit 最大只能存放的数字是 2147483647 毫秒,这就意味着,如果 setTimeout 设置的延迟值大于 2147483647 毫秒(大约 24.8 天)时就会溢出,这导致定时器会被立即执行】

    5、使用 setTimeout 设置的回调函数中的 this 不符合直觉

宏任务和微任务

  • 为了协调主线程任务有条不紊的在主线程上执行,页面进程引入了消息队列和事件循环机制,渲染进程内部会维护多个消息队列,比如延迟执行队列和普通消息队列。然后主线程采用一个for循环,不断从这些任务队列中取任务出来并执行,我们把这些消息队列中任务称为宏任务

  • 微任务就是一个需要异步执行的函数,执行时机是在主函数执行结束之后,当前宏任务结束之前

  • 微任务和宏任务是绑定的,每个宏任务执行时,会创建自己的微任务队列

  • 微任务的执行时长会影响到当前宏任务的时长

  • 在一个宏任务中,分别创建一个用于回调的宏任务和微任务,无论什么情况下,微任务都早于宏任务执行

  • MutationObserver 替换 Mutation Event:1、通过异步操作解决了同步操作的性能问题;2、通过微任务解决了实时性的问题

协程

协程是一种比线程更加轻量级的存在。你可以把协程看成是跑在线程上的任务,一个线程上可以存在多个协程,但是在线程上同时只能执行一个协程,比如当前执行的是 A 协程,要启动 B 协程,那么 A 协程就需要将主线程的控制权交给 B 协程,这就体现在 A 协程暂停执行,B 协程恢复执行;同样,也可以从 B 协程中启动 A 协程。通常,如果从 A 协程启动 B 协程,我们就把 A 协程称为 B 协程的父协程。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程

对async和await的深入理解

  • async/await的基础技术就是生成器和Promise(生成器:yield是交出主线程控制器,gen.next()是恢复协程)

  • async函数返回的是一个Promise对象

    async function foo() {
        return 2
    }
    console.log(foo()) // Promise {<resolved>: 2}
    
  • 代码案例

    async function foo() {
        console.log(1)
        let a = await 100
        console.log(a)
        console.log(2)
    }
    console.log(0)
    foo()
    console.log(3)
    输出结果 0 1 3 100 2
    

1.png

对微任务和宏任务的思考题

async function foo() {
   console.log('foo')
}
async function bar() {
   console.log('bar start')
   await foo()
   console.log('bar end')
}
console.log('script start')
setTimeout(function () {
   console.log('setTimeout')
}, 0)
bar();
new Promise(function (resolve) {
   console.log('promise executor')
   resolve();
}).then(function () {
   console.log('promise then')
})
console.log('script end')