2.2 V8消息循环系统

225 阅读2分钟

一、V8为什么需要消息循环系统

由于javascript是单线程语言,有些大的任务如果执行比较长,会阻塞其他任务的指令,于是v8需要一个消息循环系统,将异步的宏任务(setTimeout、setInterval、fs.readFile)放到消息队列里面,这些宏任务并不阻塞主线程的运行。在宏任务结束之前,也就是清空调用栈的时候,系统会检查微任务队列(promise.reslove、promise.then)是否有任务并将它们执行完,在node环境下还有nextTick队列(process.nextTick,优先级比微任务队列高, 这时候消息循环系统才从宏任务队列中取出下一个任务,如此循环反复,这就是消息循环系统。

image.png

二、v8宏任务中异步函数是如何实现回调执行的

1、什么是回调函数?

某个函数作为参数传递给某个函数或环境,该函数在函数内调用,比如setTimeout(()=>{},1000),第一个参数是setTimeout在1s后需要执行的回调函数;

2、回调函数的类型

  • 异步回调函数:在执行函数外部被执行,如setTimeout(()=>{},1000),setTimeout函数的第一个参数为异步函数,他是在1000后,在执行函数外部被执行
  • 同步回调函数:它执行函数内部被执行,如forEach((i)=>{}),forEach函数的第一个参数为同步函数,它是在函数内被执行

3、UI线程处理异步回调任务的架构

image.png

三、v8是如何实现宏任务和微任务的

1、什么是宏任务?

消息队列等待主线程执行的任务

2、列举宏任务settimeout,消息队列、主线程、调用栈的关系

  • 1、从消息队列取出宏任务settimeout

image.png

  • 2、创建foo函数上下文并压入栈中

image.png

  • 3、执行settimeout,将foo封装任务放到消息队列中

image.png

  • 4、当前宏任务结束后,清空调用栈

image.png

  • 5、等一定时间后,从消息队列中取出setimeout封装的回调宏任务执行

image.png

2、什么是微任务?

属于异步执行的函数,在宏任务结束之前,也就是调用栈在清空全局作用域之前,会执行微任务队列里面的任务;在执行完当前宏任务的微任务之前,消息队列的其他宏任务是不会被执行;微任务队列放在调用栈中的全局上下文中;可以手动通过queueMicrotask去创建微任务队列

以下是执行pomise.reslove的时候会放到微任务队列并执行 image.png