event loop到底做了什么

记录自视频What the heck is the event loop anyway? – Philip Roberts

js是一个单线程语言,只有一个调用栈(call stack),在同一时间只能做一件事情。

one thread == one call stack == one thing at a time

当调用一个函数的时候,我们把这个函数的执行上下文push到调用栈中,当函数执行完毕再将它pop出来。

虽然js在运行时是one time one thing,但是浏览器除了js引擎之外还提供了其他东西,比如一些API,这是一些可以调用的其他线程。比如处理定时器的、ajax的等接口等。

当我们使用了setTimeout,对应的webapi会进行计时,在计时完毕后将回调函数push到任务队列中去。

event loop所做的事情就是观察stack和任务队列。
当stack为空时,就将任务队列中的第一个东西取出并push到stack中。

因此像setTimeout(func,0)这种用法,就是为了推迟func的执行。虽然setTimeout(func,0)使得func马上就被加入到了任务队列中,但是还是要等到stack为空后event loop才能去取任务队列中的func到stack中然后执行。

所有那些webapi都是相同的工作方式,如ajax请求、事件处理。

这里写图片描述

我们总说UI渲染和js执行是一个线程,具体是什么意思呢?
相对于任务队列来说,还有一个负责render的队列为render队列,就是渲染队列。和任务队列一样,渲染队列也只是在stack为空时才会被event loop调用,并且渲染队列的优先级比任务队列高。
我们知道,一般浏览器以16.6ms为一个周期进行render。也就是16.6ms 渲染队列中会出现渲染任务,当stack不为空时,这个渲染任务就被阻塞了。而当stack为空时,如果当前渲染队列中需要render,event loop就会取出push到stack中,若当前正好是render 的间隙,event loop可能就会去取任务队列中的任务到stack中执行。

event loop规范

HTML5规范里有Event loops这一章节(读起来比较晦涩,只关注相关部分即可)。

  • 每个浏览器环境,至多有一个event loop。
  • 一个event loop可以有1个或多个task queue。
  • 一个task queue是一列有序的task,用来做以下工作:Events task,Parsing task, Callbacks task, Using a resource task, Reacting to DOM manipulation task等。

macrotack与microtask?

上面所说的task就是macrotask,
而microtask在ES2015规范中称为Job。

macrotask

  • script
  • setTimeout
  • setInterval
  • setImmediate
  • I/O

而microtask包括:

  • process.nextTick
  • promise
  • Object.observe

其实microtask就相当于一种插队操作,不同于macrotask每次都会添加到任务队列的队尾,会在下一个tick才执行,microtask则会在下一个tick之前执行。
因此针对如下代码:

Promise.resolve(42).then(console.log(1));
setTimeout(function(){console.log(2)},0)

最终的结果是1,2。因为Promise的then会在下一个tick前运行,而setTimeout则会在当前栈空了的情况下才被执行,也就是下一个tick才会执行,因此最终输出1,2。

还有一种解释就是,浏览器会先执行一个macrotask,之后取出microtask中的所有任务并顺序执行;之后再取macrotask的一个任务,如此周而复始……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值