jascript事件循环机制

强转星轨
• 阅读 1819

      事件循环机制控制了javascript代码的执行顺序。我们都知道javascript是单线程,这个线程中拥有唯一的一个事件循环。(新标准web workker有多线程的概念。)而事件循环机制主要以来调用栈来处理执行顺序,依靠任务队列来执行代码的执行。队列的概念可以参考https://segmentfault.com/a/11...
      在一个线程中,调用栈是唯一的,但是任务队列可以是多个,并且分为macro-task(宏任务)及micro-task(微任务)两种类型。
jascript事件循环机制
      这里需要区分一个概念任务及任务源。setTimeout及Promise是任务源。他们指定具体的执行任务进入任务队列。只有回调中的函数才会进入任务队列。就像setTimeout它其实是丽姬执行的,只是它的回调函数才会延迟执行。promise也是,本身是立即执行的,但是then才会在“未来”执行。
      javascript的执行顺序是从整体代码开始做循环,之后全局上下文进入函数调用栈。直到调用栈清空。整体代码所处的macro-task执行完成,轮到micro-task任务执行。一直循环直到所有的任务执行完成。
      当然,不同的任务源的任务会进入不同的任务队列。
      具体的可以参考一下代码。
jascript事件循环机制
      1.事件循环从macro-task开始,整体代码开始执行。整体代码script进入macro-task,并且执行代码main进入调用函数调用栈。遇到第12行的打印输出start
jascript事件循环机制
      2.继续执行,遇到13行的setTimeout,它是宏任务源。便将其分发到对应的队列中。接着遇到16行的promise。promise.resolve会进入函数调用栈直接执行,因此打印promise1,接着将p.then1和p.then分发到对应的微任务队列中。继续执行代码,遇到第24行的打印便输出end。大致图示如下图。
jascript事件循环机制
      3.script执行完毕,即第一个宏任务执行完毕,开始执行微任务。现在微任务只有一个队列,里面有p1.then1,p1.then2。队列是先进先出,因此先执行p1.then1,p1.then1进入函数调用栈,输出then1。
jascript事件循环机制
      4. p1.then1执行完毕之后,出栈。但是此时的正在进行的微任务还未执行完完毕,会继续执行p1.then2,p1.then2进入函数调用栈,输出then2。此时,微任务正在进行的队列已经执行完毕。
jascript事件循环机制
      5.当微任务执行完毕之后,第一轮循环结束,进入第二轮循环,继续执行宏任务,此时setTimeout执行,进入函数调用栈,输出setTimeout1。
jascript事件循环机制
      6.此时,宏任务队列和微任务队列中都没有任务了。代码执行完毕,就不会有任何输出了。

      我们上述的代码只涉及到一个宏任务及微任务队列的情况。但如果情况更加复杂会有什么样的表现呢?大家可以看看下面的代码。根据上面的原理试着自己分析下结果~
jascript事件循环机制
jascript事件循环机制
      1.还是跟以前的例子一样,事件循环从macro-task开始,整体代码开始执行。输出start。setTimeout1,setTimeout2依次进入新的宏任务队列。p3.resolve执行,输出promise31,promise31。并将setTimeout3放入新的宏任务队列。因为setTimeout3不是整体代码中定义的,而是在promise中定义的,需要重新开启一个宏任务队列。然后p3.then1,p3.then2分别进入微任务队列。p3.resolve出栈后,整体代码继续执行,这里就不重新画图了,输出end。
jascript事件循环机制
      2.整体代码已执行完成,循环进入微任务。此时p3.then1进入函数调用栈。输出then31。遇到新的定时,将set4放入宏任务队列。遇到新的promise,继续将p4.resolve入栈。输出promise41,promise42。遇到新的定时,将set5放入宏任务队列。此时需要注意的是,在微任务中继续有promise。此时的promise.then不再进入微任务队列,而是直接执行。因此输出then41。
jascript事件循环机制
      3.微任务队列还未执行完毕,继续执行p3.then2。直接输出then32。此时微任务队列已经执行完毕,进入下一轮循环。
jascript事件循环机制
      4.新的循环开始。队列是先进先出,因此在宏任务当前队列中,set1先执行,进入函数调用栈。输出setTimeout1。遇到新的promise,继续将p1.resolve入栈。输出promise1。还是跟上看一样,在宏任务中继续有promise。此时的promise.then不再进入微任务队列,而是直接执行。直接输出then1。
jascript事件循环机制
      5.setTimeout1执行完毕,正在执行的宏任务队列还有任务,继续执行setTimeout2。setTimeout2进入函数调用栈。跟setTimeout1的分析一样,陆续输出setTimeout2,promise2,then2。
jascript事件循环机制
      6.当前宏任务执行完毕,微任务内没有可执行的队列。继续下一轮循环。执行set3。输出setTimeout3。遇到新的promsie,还是跟上面的分析一样,输出promise5,then5。因为微任务一直没有可执行的队列。宏任务内的队列依次执行,输出setTimeout4,setTimeout5。
jascript事件循环机制

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
菜园前端 菜园前端
2年前
什么是宏任务与微任务?
原文链接:事件循环机制在事件循环中,每进行一次循环操作称为tick,每一次tick的任务处理是比较复杂的。关键步骤如下:1.执行一个宏任务2.执行过程中如果遇到微任务,就将它添加到微任务的任务队列中3.宏任务执行完毕后,立即执行当前微任务队列中的所有微任务
Stella981 Stella981
3年前
Javascript解析机制 执行机制
HTML5学堂:在学习JavaScript过程中,我们需要了解事件的机制是怎么执行的?本文将会提到JavaScript事件机制的解析,希望对大家有帮助!javascript解析的过程主要分为两个阶段,分别是编译与执行阶段。在编译期,javascript解释器将完成对javascript代码的预处理,即将javascript代码转换为字节码。在执行
Stella981 Stella981
3年前
Javascript并发模型和事件循环
JavaScript的"并发模型"是基于事件循环的,这个并发模型有别于Java的多线程,javascript的并发是单线程的。Javascript中有个重要一块,EventLoop,能把单线程的JavaScript使出多线程的感觉。"EventLoop是一个程序结构,用于等待和发送消息和事件。(aprogrammingconst
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
JS异步的底层原理:单线程加事件队列
异步的底层原理:单线程事件队列。js的代码执行时单线程的,所谓单线程:就是js代码时从上到下按顺序依次执行的,一次只能做一件事情。事件队列可以看作一个容器,这个容器存储着js的回调函数,只有js代码执行结束后,才会去事件队列中调用这些回调函数。例:1//以下的代码先执行for循环,再输出sum值,然后输出正常代码执行,最后
Stella981 Stella981
3年前
JavaScript 事件循环机制
javascript是一门单线程的非阻塞的脚本语言。单线程意味着javascript在执行代码的任何时候,都只有一个主线程来处理所有的任务。那么javascript引擎是如何实现这一点的呢?因为事件循环(eventloop)。先上图:!event_loop(https://oscimg.oschina.net/oscnet/up6
Stella981 Stella981
3年前
Android的消息循环与Handler机制理解
一、概念1、事件驱动型什么是事件驱动?就是有事了才去处理,没事就躺着不动。假如把用户点击按钮,滑动页面等这些都看作事件,事件产生后程序就执行相应的处理方法,就是属于事件驱动型。2、消息循环把需要处理的事件表示成一个消息,并且把这个消息放入一个队列。消息循环就是一循环,for或者while都一样。从消息队列里面取出未处理的消息,然后调用该消息的
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
强转星轨
强转星轨
Lv1
人面不知何处去,桃花依旧笑春风。
文章
4
粉丝
0
获赞
0