浏览器事件循环机制

广告位招租
扫码页面底部二维码联系

在众多话题中,浏览器事件循环机制这个话题【作者:唐霜】【关注微信公众号:wwwtangshuangnet】显得格外重要,面试中也好,日常开发讨论时【未经授权禁止转载】本文作者:唐霜,转载请注明出处。也好,了解由于事件循环机制所带来的执行时转载请注明出处:www.tangshuang.net原创内容,盗版必究。序,几乎可以成为一件用来炫技的事情。那么原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。,本文就来聊一聊浏览器事件循环机制。

本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net

浏览器的角色【未经授权禁止转载】

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。原创内容,盗版必究。

很多文章一上来说“javascript的【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。事件循环”,我可以负责任的告诉你,这个说本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net法本身就错了,这些文章估计也就是凑数的。【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】“事件循环”是浏览器遵循HTML标准著作权归作者所有,禁止商业用途转载。而实现的,既然是HTML标准,根js这门【本文首发于唐霜的博客】【本文受版权保护】语言本身没关系。我们知道,javascr【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。ipt是单线程执行语言,那么如果在整个时本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】空中,只有这一根线程在跑程序,哪来的事件【版权所有】唐霜 www.tangshuang.net【转载请注明来源】循环呢?javascript是一门语言,【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net它的本质在于其语法、数据类型和结构、核心【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。特性(如继承性、全剧作用域、动态类型变量【本文首发于唐霜的博客】原创内容,盗版必究。),而至于你要如何去运行由js写的代码,【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。则是你选择用什么工具去执行它。除了v8以本文作者:唐霜,转载请注明出处。原创内容,盗版必究。外,用来执行js的引擎还有firefox原创内容,盗版必究。未经授权,禁止复制转载。的SpiderMonkey,IE的JSc【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】ript等等。当然,目前来说,v8是最火【原创不易,请尊重版权】未经授权,禁止复制转载。的,也是最快的。然而,单就v8引擎,根本【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。干不了事情,要让js工作,还要在v8外面本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net套上一层又一层的工具,形成一套运行时(r【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】untime)环境,除了浏览器之外,no【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】dejs就是大名鼎鼎的另外一套js运行时【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。环境,除了这两个熟知平台之外,还有嵌入式未经授权,禁止复制转载。【原创内容,转载请注明出处】运行环境,它们采用了一个叫quickjs【本文受版权保护】原创内容,盗版必究。的js引擎。我们今天要讲的事件循环,发生著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。在这样的运行时环境中,也就是浏览器,这样【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。一个大平台上。

【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。【未经授权禁止转载】原创内容,盗版必究。

浏览器是多线程的(这里不包含webwor【本文首发于唐霜的博客】【原创内容,转载请注明出处】ker),这一点几乎是众所周知。这里的多本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net线程,我们摊开来看,最主要的就是JS引擎本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】线程、GUI渲染引擎线程。

【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net

你应该知道这样一个事实,异步,是浏览器行【本文受版权保护】【本文受版权保护】为中非常大特点的一个。什么是异步呢?就是转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。一个任务,并不是立即执行,而是要等待一会【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】儿再执行。那在等待啥呢?在等待这个过程中【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。,通过什么方式,它知道应该结束等待,执行著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】那个异步任务呢?

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net

所以,在js执行的那个线程之外,事件循环著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】线程就是帮助js线程完成这个等待和结束等未经授权,禁止复制转载。【本文首发于唐霜的博客】待过程的另外一条线程。

【本文受版权保护】【原创不易,请尊重版权】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。

执行栈(Call Stack)转载请注明出处:www.tangshuang.net

未经授权,禁止复制转载。原创内容,盗版必究。【版权所有,侵权必究】【未经授权禁止转载】本文作者:唐霜,转载请注明出处。

“栈”是一个先进后出的数据结构。js的执原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】行,是以函数为一等公民,以执行栈的形式执著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net行作用域上下文。我们来看一段代码:

转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】
function main() {
  a()
  b()
}

function a() {
  c()
}

function b() {}
function c() {}

main()

你知道它们的执行顺序是 main->【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】;a->c->b,在这样执行本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net过程中,会形成执行栈,当一个函数开始执行著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。时,被压入栈顶,执行完时,弹出栈;如果在转载请注明出处:www.tangshuang.net【未经授权禁止转载】这个函数执行过程中,调用了另外一个函数,【原创不易,请尊重版权】【作者:唐霜】那么这个被调用的函数会被压入到这个栈顶,【版权所有】唐霜 www.tangshuang.net【转载请注明来源】执行完之后,就会被弹出,回到还在栈顶的那本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。个函数的剩下部分。

本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。【转载请注明来源】【原创内容,转载请注明出处】

执行栈示意图原创内容,盗版必究。

转载请注明出处:www.tangshuang.net【作者:唐霜】原创内容,盗版必究。【转载请注明来源】【原创内容,转载请注明出处】

如上图所示意,黄色区域内是执行栈。当一段本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】代码被执行起来,js执行栈的一个特点是不本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net被打断(C语言等语言的一些执行可以被打断本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】)。正在执行的所有这些函数,必须是按照代【版权所有,侵权必究】【版权所有,侵权必究】码中的顺序和执行栈的模式,一次性完成,而【作者:唐霜】【关注微信公众号:wwwtangshuangnet】在这个过程里面,对于浏览器来说,不能干其著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。他事,必须等main函数执行完,拿到结果未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net,才能干其他的事情(例如在main中触发【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】的界面的重新渲染,浏览器需要通过渲染引擎本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。重新渲染界面)。这也是为什么js慢的原因本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。之一。

【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。

任务队列(Tasks Queue)原创内容,盗版必究。

原创内容,盗版必究。【作者:唐霜】原创内容,盗版必究。

“队列”是一个区别于栈的数据结构,其特征转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net是先进先出。浏览器通过内部实现的多个任务著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】队列,来调控任务的先后顺序。那么什么是“【作者:唐霜】转载请注明出处:www.tangshuang.net任务”呢?一个函数被压入执行栈中开始被执原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。行,经过执行栈模式执行,到最好栈被清空的【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】这个过程(上文示意图展示的过程),这样一著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】个过程被称为“一次任务”。

【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net

在上面的示意图例子中,我们经历了最简单的【转载请注明来源】本文作者:唐霜,转载请注明出处。js单线程运行过程。但是,现在,我们在c【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】函数中,增加一个需要进行网络I/O的任务【本文受版权保护】本文版权归作者所有,未经授权不得转载。,也就是我们熟知的ajax,而且我们都知【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】道这是异步的。

未经授权,禁止复制转载。【本文首发于唐霜的博客】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net
function c() {
  fetch('http://xxx.com/api').then(e)
}

async function e(res) {
  const data = await res.json
  console.log(data)
}

看,我们熟知的代码来了。从现在我已知的现本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。象,我们知道,fetch函数是一个异步函本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】数,它不会阻塞js的执行,在执行时间上,【作者:唐霜】【作者:唐霜】几乎没有花时间,我们就让c函数结束,开始【原创内容,转载请注明出处】【作者:唐霜】d函数运行。

【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】【本文首发于唐霜的博客】

实际上,fetch语句,发起了一个新任务【原创内容,转载请注明出处】【转载请注明来源】,这个新任务和当前执行栈中正在运行的任务原创内容,盗版必究。【作者:唐霜】,属于同一个级别。这个新任务被交给 We【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】b API(也就是网络请求I/O接口fe本文版权归作者所有,未经授权不得转载。【作者:唐霜】tch,在浏览器的另外线程中执行,下文细本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。述),当Web API完成网络I/O之后转载请注明出处:www.tangshuang.net【作者:唐霜】,又会反过来,把该任务交还给js线程(主本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。线程),好让这个任务(实际上也就是我们常著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。说的回调函数)在执行栈中被运行。

【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net【版权所有,侵权必究】【版权所有,侵权必究】

横向箭头线表示任务线,可以理解为两个不同未经授权,禁止复制转载。【未经授权禁止转载】线程,黑色为主线程,绿色为网络I/O线程本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】。总向箭头线可以理解为线程之间交还消息。本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。黄色区域表示一个任务,不是一个栈,理解时【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】应该注意这一点。

著作权归作者所有,禁止商业用途转载。【作者:唐霜】【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。

那么这个交还过程是怎么做到的呢?这个交还原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。过程是通过将被交还的任务,放入到一个“任本文作者:唐霜,转载请注明出处。【转载请注明来源】务队列”中而完成的。

【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】

JS执行的任务队列【版权所有】唐霜 www.tangshuang.net

【未经授权禁止转载】【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net

【原创不易,请尊重版权】MDN的文档本文作者:唐霜,转载请注明出处。中,并没有“任务队列”的说法,而是称为“【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。消息队列”(message queue)【原创内容,转载请注明出处】【作者:唐霜】,我认为这样称反而不容易理解。

【未经授权禁止转载】【版权所有,侵权必究】【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net

MDN将任务称为消息,你细品这里的这句话转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。,a message 实际上就是 set【版权所有,侵权必究】【作者:唐霜】Timeout 的第一个参数,也就是回调著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。函数,将函数称为 message 不容易【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】理解,称为任务反而好理解一些

本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】

任务是在什么时候被推送到任务队列中的呢?原创内容,盗版必究。【原创内容,转载请注明出处】是在Web API完成对应的操作之后,例【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。如由fetch发起的网络I/O操作,当网【作者:唐霜】未经授权,禁止复制转载。络请求回来之后,回调函数(也就是任务)被转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】推入队列等待被执行,由setTimeou【原创内容,转载请注明出处】未经授权,禁止复制转载。t发起的定时器任务,在定时器到时之后,回【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】调函数被推入队列等待执行(需要注意,se原创内容,盗版必究。原创内容,盗版必究。tTimeout的第二个参数,是一个参考转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。值,表示最小等待时间,而并非确定值,这在【本文受版权保护】【原创内容,转载请注明出处】MDN的文档中已经清楚的表示了)。

原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。

那么这个任务队列被放在哪里呢?任务队列实【本文受版权保护】【本文首发于唐霜的博客】际上是一个独立的服务,就像你使用Kafk【转载请注明来源】转载请注明出处:www.tangshuang.neta一样,它有自己的工作模式,理论上,它和未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】js主线程也是分开的,它在另外一个线程中【原创不易,请尊重版权】【本文受版权保护】运行。在整个过程中,由js线程发起的任务未经授权,禁止复制转载。【本文首发于唐霜的博客】,交给Web API去执行时,也会把回调【未经授权禁止转载】未经授权,禁止复制转载。函数的指针交给Web API(在js线程未经授权,禁止复制转载。【转载请注明来源】和Web API对应任务线程之间传递的东【转载请注明来源】【作者:唐霜】西,我认为倒是可以用消息,也就是mess【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】age,来表示),而函数被存放在js堆内著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net存中,保持着它的上下文。被放在任务队列中本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】的任务,实际上,只是拥有一个指针信息,当【作者:唐霜】【原创不易,请尊重版权】任务被取出,实际上是从js线程的堆内存中【本文受版权保护】原创内容,盗版必究。取出该指针对应的函数,压入栈中开始执行。

原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】【本文受版权保护】未经授权,禁止复制转载。原创内容,盗版必究。

另外需要注意一点,任务队列不是“队列”,未经授权,禁止复制转载。【作者:唐霜】而是“set”(集合)。这在WHATWG的标准【版权所有,侵权必究】文件中说的很清楚,“因为事件循环执行模式【原创不易,请尊重版权】【未经授权禁止转载】的第一步,是从被选中的队列中,抓取第一个【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】可以被执行的任务,而非弹出队列头部(也就【本文受版权保护】【关注微信公众号:wwwtangshuangnet】是队列先进先出模式)第一个任务。”也就是转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】说,浏览器的任务队列并不是完全按照队列的本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】模式执行,而是有选择的,按照一定条件先选著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】一个队列(浏览器中会有多个队列),然后从未经授权,禁止复制转载。【本文首发于唐霜的博客】该队列中选第一个可以被执行的任务(即使有本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】任务更靠前,但它可能目前还不能被执行)。【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】那么,什么是事件循环呢?

本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】【转载请注明来源】未经授权,禁止复制转载。

事件循环(Event Loop)【访问 www.tangshuang.net 获取更多精彩内容】

【未经授权禁止转载】【本文受版权保护】转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】

现在,我们来到了本文最核心的目标。事件循【未经授权禁止转载】原创内容,盗版必究。环,实际上,是浏览器从任务队列中如何取出【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】一个任务,丢到执行栈中,当执行栈重新变空【转载请注明来源】【本文首发于唐霜的博客】之后,又如何运作的一套模式。事件循环被放本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net在另外一个独立线程中运行。它的主要工作,本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net是按照一定逻辑从任务队列中取任务,交给j【作者:唐霜】本文版权归作者所有,未经授权不得转载。s主线程放入执行栈中执行,在执行栈为空之【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。后,又执行这一个过程。

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。【版权所有,侵权必究】
while (queue.waitForMessage()) {
  queue.processNextMessage()
}

它是一个无限执行的“死循环”,一直在监控【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】着执行栈和任务队列的情况,并做着搬运工一【作者:唐霜】本文版权归作者所有,未经授权不得转载。般的工作。这也就是为什么它叫“事件循环”本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】这个名字的原因。

转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】【原创不易,请尊重版权】【本文首发于唐霜的博客】

我们可以认为事件循环位于队列和栈之间,做原创内容,盗版必究。本文作者:唐霜,转载请注明出处。着一个无限运转搬运工的工作。

【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。

但是,宏观上,我们把上图中整个系统称为“本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。事件循环机制”的全貌,而不是把仅存在于任【转载请注明来源】转载请注明出处:www.tangshuang.net务队列和执行栈之间的这个控制逻辑称为事件【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。循环。也就是说,我们日常讨论中,包含js转载请注明出处:www.tangshuang.net【本文受版权保护】主线程、Web API任务线程(网络I/【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。O所使用的线程和定时器所使用的线程,可能著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。不是同一个)、任务队列线程等等相关的东西【版权所有,侵权必究】【本文受版权保护】,全部集合到一个概念里面,这个概念就是“著作权归作者所有,禁止商业用途转载。【本文受版权保护】事件循环”。

【转载请注明来源】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】

宏任务与微任务【原创不易,请尊重版权】

【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】

在事件循环中,由js所产生的新任务,被放本文作者:唐霜,转载请注明出处。【转载请注明来源】到任务队列中。但是,我们前面讲过了,任务【作者:唐霜】原创内容,盗版必究。队列不只一个。理论上讲,我认为最少需要3【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。个任务队列:宏任务队列、ui渲染任务队列未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】、微任务队列。那么,什么是宏任务(mac本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netrotask),什么是微任务(micro【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。task)呢?

本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【本文受版权保护】【原创内容,转载请注明出处】

别急,在此之前,我们先解释一下,为啥ui【本文首发于唐霜的博客】【本文受版权保护】渲染也要占一个任务队列。大家都听说过帧的原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】问题,由于屏幕刷新来渲染界面变动,所以新【转载请注明来源】转载请注明出处:www.tangshuang.net界面渲染必须在下一次刷新之前准备好要渲染本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net的内容。我们也听过16ms的帧率。那是浏本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】览器按屏幕1分钟刷新1000次的频率设计【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】的。我们可以通过调用requestAni未经授权,禁止复制转载。未经授权,禁止复制转载。mationFrame来利用这个任务队列【关注微信公众号:wwwtangshuangnet】【本文受版权保护】完成一些需要按照刷新率来实现的周期性任务【原创内容,转载请注明出处】【本文首发于唐霜的博客】

未经授权,禁止复制转载。【原创不易,请尊重版权】未经授权,禁止复制转载。

那么什么是宏任务呢?在js脚本中,通过调【本文首发于唐霜的博客】【作者:唐霜】用setTimeout, DOM事件绑定本文作者:唐霜,转载请注明出处。【作者:唐霜】,网络I/O等,由js产生的新任务,被称著作权归作者所有,禁止商业用途转载。【作者:唐霜】为宏任务。宏任务队列可能有多个,理论上,【转载请注明来源】著作权归作者所有,禁止商业用途转载。不同类型的宏任务(由不同Web API完【转载请注明来源】【关注微信公众号:wwwtangshuangnet】成的)会被放在不同的宏任务队列中,它们是【原创不易,请尊重版权】未经授权,禁止复制转载。并列的,所以,当你同时执行一个setTi【作者:唐霜】【作者:唐霜】meout和一个fetch的时候,你是不【版权所有,侵权必究】【版权所有,侵权必究】知道它们的回调是会谁先执行的,这个是无法未经授权,禁止复制转载。【版权所有,侵权必究】控制的,事件循环在选择使用哪一个宏任务队未经授权,禁止复制转载。未经授权,禁止复制转载。列时,主要是看宏任务队列中的任务是否可被本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net执行,如果存在极端情况,比如多个宏任务队转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。列的任务都可以被执行,那么具体挑选哪个任【本文受版权保护】本文作者:唐霜,转载请注明出处。务执行具有运气成分,但这种情况一般很少见【作者:唐霜】本文版权归作者所有,未经授权不得转载。,即使出现,也无所谓。

【未经授权禁止转载】【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net

宏任务就是我们上文反复提到的任务。【本文首发于唐霜的博客】

原创内容,盗版必究。未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】

那么,微任务呢?微任务也是由js执行过程【本文受版权保护】【本文受版权保护】中产生的新任务,但是它有很大的不同。“微【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】任务队列不是(宏)任务队列”,这是WHA【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】TWG标准文档里面的一句话。宏任务队列可【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。能有多个,而微任务队列,至始至终只有一个转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。。所以,微任务的执行,和队列的执行模式一【本文受版权保护】未经授权,禁止复制转载。模一样,它不挑剔。微任务是怎么产生的呢?原创内容,盗版必究。未经授权,禁止复制转载。它的产生和宏任务也是一样的,只是产生方式原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】不同,通过Promise.then/ca转载请注明出处:www.tangshuang.net原创内容,盗版必究。tch, MutationObserve本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】r产生的都是微任务。

【本文受版权保护】原创内容,盗版必究。【作者:唐霜】【本文受版权保护】本文版权归作者所有,未经授权不得转载。

上面提到,事件循环会在执行栈重新变空之后转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】,取出一个新任务压入栈中执行。但是,实际转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net上,宏任务和微任务在这个里面执行时机不同【原创内容,转载请注明出处】未经授权,禁止复制转载。。事件循环机制,会在每执行完一个宏任务之本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。后,立即在微任务队列中取出第一个微任务进【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。行执行,这个微任务执行完之后,还会继续在【作者:唐霜】【原创不易,请尊重版权】微任务队列中取出第一个执行,值到微任务队本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。列中不再有微任务为止,才会重新到宏任务队转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net列中取宏任务执行。

转载请注明出处:www.tangshuang.net【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net

微任务队列必须在每一个宏任务执行完之后被【未经授权禁止转载】【本文首发于唐霜的博客】消费空。

本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。

另外一个事实是,在这些新任务中产生的宏任【原创不易,请尊重版权】未经授权,禁止复制转载。务,会被加入到宏任务队列,新产生的微任务【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】会被加入到微任务队列。这里面就会出现一种【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】情况,无论是宏任务,还是微任务,都可能产【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。生新的微任务。如果持续不断的在微任务队列未经授权,禁止复制转载。【转载请注明来源】被消费干净之前产生微任务,那么宏任务永远著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】没有机会被执行。一定要避免这种情况发生。

【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net【未经授权禁止转载】【本文受版权保护】

另外一个非常重要的话题是,宏任务和微任务未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。的时序问题。我录制了一个视频,用动态的效原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】果来演示一段程序由于宏任务微任务所带来的本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。时序效果。

原创内容,盗版必究。转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】

本文版权归作者所有,未经授权不得转载。【作者:唐霜】【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】

当然,视频中还有一些描述不当的地方。但主【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。要演示了宏任务微任务带来的执行时序效果。

【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】

小结【原创不易,请尊重版权】

转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【作者:唐霜】

本文详细阐述了浏览器中的事件循环机制,虽【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net然细节处可能还不够具体,但是在整体上,已未经授权,禁止复制转载。【原创内容,转载请注明出处】经足以让你了解事件循环究竟是怎么一回事了转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net。可以说,事件循环机制是让js在浏览器中未经授权,禁止复制转载。【转载请注明来源】实现异步编程的核心驱动,没有事件循环应该转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。也就没有js异步编程了。在php编程中,原创内容,盗版必究。本文作者:唐霜,转载请注明出处。由于没有内置的事件循环,让php异步编程【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】变得非常复杂,甚至还要依赖第三方服务才能【版权所有,侵权必究】转载请注明出处:www.tangshuang.net完成,然而,在js所有运行环境中,都支持本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。事件循环,包括nodejs和quickj著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】s。现在,我们再回头问,为什么叫“事件循【转载请注明来源】【版权所有】唐霜 www.tangshuang.net环”,“循环”这个点我想你已经了解了,关著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】于“事件”,你会发现,实际上有关 Web【原创内容,转载请注明出处】【本文首发于唐霜的博客】 API的操作,都是一个“订阅事件-发布【版权所有,侵权必究】【本文首发于唐霜的博客】事件消息”的过程,因此,MDN会把Web【转载请注明来源】【作者:唐霜】 API完成自身操作通知给主线程的东西(本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】也就是推到任务队列中的东西)叫做“消息”著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。,它是基于I/O操作等已经完成这个“事件【原创不易,请尊重版权】【原创内容,转载请注明出处】”而给出的。同样的道理,在“栈执行完毕已本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net经清空”这个事件上,它也给出了“到任务队【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。列中取任务过来执行”的消息。将这些东西综本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】合起来理解,或许我们就可以加深其印象了。【关注微信公众号:wwwtangshuangnet】【转载请注明来源】而且,还有一个点,如果将“执行栈”脱离“原创内容,盗版必究。转载请注明出处:www.tangshuang.net事件循环”这个话题单独来讲,其实没什么意【本文受版权保护】本文作者:唐霜,转载请注明出处。义。为什么要设计一个栈结构呢?说到底,是本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net为了当栈被重新清空时,可以发出一个消息,【转载请注明来源】未经授权,禁止复制转载。让事件循环可以从队列中取出新任务来执行。【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。如果不是为了实现这个目的,设计一个栈显得【原创内容,转载请注明出处】原创内容,盗版必究。毫无意义。如果你对文章中的问题有疑问或觉未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net得不足,欢迎在下方评论区给我留言。<原创内容,盗版必究。转载请注明出处:www.tangshuang.net;完>

著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】【未经授权禁止转载】

2020-03-11 5156 ,

为价值买单,打赏一杯咖啡

本文价值51.56RMB