前言

JS是一门单线程语言,单线程就意味着,所有的工作须要排队,前一个工作完结,才会执行下一个工作。这样所导致的问题是:如果JS执行的工夫过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的觉。为了解决这个问题,JS中呈现了同步和异步。他们的本质区别是:一条流水线上各个流程的执行程序不同。在讲JS工作执行机制前,先要理解一下什么是同步工作与异步工作。

同步工作:即主线程上的工作,依照程序由上⾄下顺次执⾏,以后⼀个工作执⾏结束后,能力执⾏下⼀个工作。

异步工作:不进⼊主线程,⽽是进⼊工作队列的工作,执行结束之后会产生一个回调函数,并且告诉主线程。当主线程上的工作执行完后,就会调取最早告诉本人的回调函数,使其进入主线程中执行。

1. 事件循环Event Loop概念介绍

  • 事件循环Event Loop又叫事件队列,两者是一个概念

事件循环指的是js代码所在运行环境(浏览器、nodejs)编译器的一种解析执行规定。事件循环不属于js代码自身的领域,而是属于js编译器的领域,在js中探讨事件循环是没有意义的。换句话说,js代码能够了解为是一个人在公司中具体做的事件, 而 事件循环 相当于是公司的一种规章制度。 两者不是一个层面的概念。

2. 微工作、宏工作概念介绍

  1. 微工作与宏工作就属于js代码的领域
  2. js代码次要分为两大类: 同步代码、异步代码
  3. 异步代码又分为:微工作与宏工作

3. 事件循环Event Loop执行机制

  • 1.进入到script标签,就进入到了第一次事件循环.
  • 2.遇到同步代码,立刻执行
  • 3.遇到宏工作,放入到宏工作队列里.
  • 4.遇到微工作,放入到微工作队列里.
  • 5.执行完所有同步代码
  • 6.执行微工作代码
  • 7.微工作代码执行结束,本次队列清空
  • 寻找下一个宏工作,反复步骤1

    • 以此重复直到清空所以宏工作,这种一直反复的执行机制,就叫做事件循环

画了一张图来形容事件循环

4.易错点

(1). promise自身是一个同步的代码(只是容器),只有它前面调用的then()办法外面的回调才是微工作

(2). await左边的表达式还是会立刻执行,表达式之后的代码才是微工作, await微工作能够转换成等价的promise微任务分析

(3). script标签自身是一个宏工作, 当页面呈现多个script标签的时候,浏览器会把script标签作为宏工作来解析

看到这里,对事件循环应该有所理解了,给大家看几道面试题。

一.

1.先执行主线程上的log(1)

2.当有两个await时,只有第一个await左边的代码会立刻执行log(4),前面的几行代码都会放入微工作队列中。

3.执行主线程上的log(6)

4.执行第4行至第6行的微工作

二.

1.先执行主线程上的1,5,7

2.主线程的同步工作执行结束后,会先执行微工作。执行Promise的then办法里的代码,打印6

3.微工作执行结束后,最初执行定时器里的宏工作,打印2,3,4

三.

参考 前端进阶面试题具体解答

1.先执行主线程上的同步代码,打印1

2.执行第9行的函数,进⼊async1外部,async1其实是申明了⼀个promise,promise是同步代码,会程序执⾏打印async2函数里的4 ,只有.then⾥⾯的代码会加⼊微工作队列⾥,这⾥相当于执⾏了async2()之后,再将前面的代码加⼊⼀个微工作队列中。

3.回主线程中,遇到setTimeout(),加⼊到宏工作队列

4.主线程持续往后执⾏,前⾯说过,promise是同步代码,.then后⾯的回调会加⼊微工作队列,所以会打印13⾏的7

5.主线程执⾏实现,开始执⾏微工作队列内的工作,遵循先进先出的准则,打印第四⾏的2。而后接着执行第5行第二个awaite左边的代码,打印5。第6行这个时候就被退出微工作队列。

6.接着会执行第二个微工作,也就是16行代码,打印8。第17行的then这个时候也会退出微工作队列。再顺次执行第6行和第17行的两个微工作,打印3和9

7.微工作执⾏完结,开始执⾏宏工作setTimeout,打印11⾏的6.

总结

  1. 所有同步工作都在主线程上执行,造成一个执行栈(call stack)。
  2. 遇到异步工作, 进入异步解决模块并注册回调函数; 等到指定的事件实现(如ajax申请响应返回, setTimeout提早到指定工夫)时,异步解决模块会将这个回调函数移入异步工作队列。
  3. 当栈中的代码执行结束,执行栈中的工作为空时,主线程会先查看微工作队列中是否有工作,如果有,就将微工作队列中的所有工作顺次执行,直到微工作队列为空; 之后再查看宏工作队列中是否有工作,如果有,则取出第一个宏工作退出到执行栈中,之后再清空执行栈,查看微工作,以此循环,直到全副的工作都执行实现。
    以上就是我对JS执行原理的一些整顿和了解,心愿能给读者带来一些帮忙。如果有了解谬误或表述不当的中央,请斧正。
最初再给大家出一道题,能够把答案留在评论区