javascript的event loop事件循环

javascript的event loop事件循环

这是今天一个朋友发给个人一个面试题,javascript

感受还挺有意思的,java

写个博客以供分享面试

 

先看看这个面试题目:promise

观察下面的代码,写出输出结果
异步

console.log('0') setTimeout(function () {  console.log('1'); }); new Promise(function(resolve,reject){  console.log('2')  resolve(3) }).then(function(val){  console.log(val) }) console.log(4)

输出结果: “0” “2” 4 3 “1”async

 

今天主要是分析为何输出结果是这样的?这就和 javascript 的执行机制密切相关了.函数

 


 

 

Event QueueEvent Loop

 

javascript 是一门单线程的语言, 这就意味着在执行代码的时候, 都只有一个主线程来处理全部的任务.oop

咱们都知道 javascript 包括同步代码和异步代码, 那么 javascript 是怎么处理这两种状况的呢?spa

 

  • 同步和异步任务分别进入不一样的执行 场所, 同步的进入主线程,异步的进入 Event Table 并注册函数
  • 当指定的事情完成时, Event Table 会将这个函数(回调函数)移入 Event Queue
  • 主线程内的任务执行完毕为空, 会去 Event Queue 读取对应的函数,进入主线程执行
  • 上述过程会不断重复, 也就是常说的 Event Loop(事件循环)

 

这里咱们引进了 Event Queue 事件队列这一律念. 全部异步操做的回调都会进入到这里. 而后等到主线程空闲, 就会从这里调取回调执行.线程

 


 

 

setTimeout

 

setTimeout 相信你们都有使用过, 能够延时执行而且是异步执行的.

可是有时候咱们获得的结果每每是代码实际执行的时间比咱们想要延时执行的时间要久。这又是为何呢?

这就和咱们以前所说的 Event Loop 有关了, 咱们能够来具体看下 setTimeout 的执行步骤:

 

setTimeout(function () {
    asyncFn()
}, 1000);

syncFn()

 

  • asyncFn 将异步执行函数放在 Event Table, 而且开始计时
  • 开始执行 syncFn, 可是 syncFn 可能须要处理的内容不少, 执行时间超过 1 秒, 可是计时还在继续
  • 计时到达 1 秒, setTimeout 延时完成, asyncFn 进入 Event Queue 事件队列, 可是主线程还在执行, 因此只能等待
  • syncFn 执行完成, 此时 asyncFn 从事件队列中进入主线程执行

因此有时候会出现代码实际执行时间比延时时间长的状况。

 


 

 

宏任务和微任务

 

以前咱们说过异步任务会进入到事件队列中, 不一样类型的任务会进入到不一样的队列中, 好比宏任务会进入到宏任务队列中, 微任务会进入到微任务队列中.

 

微任务:promise

宏任务:setTimeout、setInterval、setImmediate

 

咱们只要记住 当当前执行栈执行完毕时会马上先处理全部微任务队列中的事件,而后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务以前执行

这时候咱们就能够解释一开始的代码执行结果了:

 

  • 主线程执行按顺序代码
  • 遇到 setTimeout, 回调进入到宏任务队列上
  • 遇到 Promise, 当即执行, then 函数进入到微任务队列
  • 同步代码执行结束, 主线程检查是否存在微任务, 发现 then, 执行
  • 微任务执行完毕, 再去查找宏任务 setTimeout, 执行
  • setTimeout 执行结束, 检查,不存在其余, 结束.

 

 

 

以上。

相关文章
相关标签/搜索