本文是V8引擎详解系列的第八篇,重点内容是关于V8引擎的消息队列,会经过单线程的特色入手来学习,逐步其消息队列的运行机制。
文末会有已经完成的系列文章的连接,本系列文章还在不断更新欢迎持续关注。javascript
因为javascript最初做为浏览器脚本语言,主要用来与用户互动、操做dom等,若是有多个线程同时操做一个DOM的状况,会致使很是难以处理,因此javascript只能设计成单线程。前端
不过现代计算机基本都是多核CPU的,纯粹的单线程会致使一些性能得不到释放,因此新的 HTML5 标准中提出了 web worker概念,容许用户额外开启线程,不过 worker 线程是彻底受主线程控制(大部分状况处理一些计算逻辑),且没有操做DOM的权限,本质上javascript仍是单线程。java
javascript只有一个主线程用来执行任务,可是同一时间只能执行一个任务也就是函数,普通的函数会造成一个任务队列排队执行,可是有些任务会很是耗时且不可控(网络请求、事件监听)等,若是让这些任务也和普通任务同样排队执行,那么执行效率低不说还会致使页面的卡死。
因而就有了异步任务,而 V8 引擎 经过消息队列 和 事件循环 系统让异步任务执行且不用排队等待执行完毕。web
消息队列是 V8引擎 除了主线程任务外,额外维护的一个队列,主要存放要执行的任务(函数)。彻底符合队列 先进先出 的特色,从队列的头部取出任务,从队列的尾部添加任务。面试
浏览器自己须要异步的场景很是多,而每一种异步操做的机制也各不相同, 消息队列能够和多种异步场景产生交互。ajax
以及一些其余的模块会将异步操做放置到消息队列中,在引擎主线程的任务都执行完成后再执行消息队列中被推送的任务。
具体以下图:vim
那么消息队列会在何时执行呢?
每次执行栈中的代码就是一个宏任务(task),而消息队列中的任务会按顺序放到下一次的宏任务(task)中,每一个宏任务(task)在执行时,V8 都会从新建立栈,而后随着宏任务(task)中函数调用,栈也随之变化,最终,当该宏任务(task)执行结束时,整个栈又会被清空,接着主线程继续执行下一个宏任务(task)。promise
而浏览器会在一个 宏任务(task) 执行结束后,在下一个 task 执行开始前,对页面进行从新渲染如图:浏览器
因为主线程执行消息队列中宏任务的时间颗粒度太粗了(主要中间有一次渲染过程),没法胜任一些对精度和实时性要求较高的场景,因此又引入了promise 机制也就是微任务如图:缓存
(本篇的重点不在于宏任务和微任务因此简单带过,可是我想表达的是,如今前端面试大几率都会问到宏任务和微任务,不少人都只会回答到宏任务和微任务的执行顺序,可是若是你回答出中间还有一个页面渲染的过程,才算真正了解)
若是你能理解上文的消息队列机制,那么事件循环就很好理解了,本质上就是
本文主要了解了关于V8引擎的消息队列的运行机制,也简单的了解了一下为何js使用单线程机制,以及简单说了一下宏任务和微任务(网上相关的好文章很是多,因此本文就不重复赘述,只是简单的点了一下容易被忽略的点)。若是有什么错误,请在评论中和做者一块儿讨论,若是您以为本文对您有帮助请帮忙点个赞,感激涕零。
vimeo.com/96425312 time.geekbang.org/column/arti…
V8引擎详解(一)——概述
V8引擎详解(二)——AST
V8引擎详解(三)——从字节码看V8的演变
V8引擎详解(四)——字节码是如何执行的
V8引擎详解(五)——内联缓存
V8引擎详解(六)——内存结构
V8引擎详解(七)——垃圾回收机制
V8引擎详解(八)——消息队列
V8引擎详解(九)——协程&生成器函数