前端开发JS:事件循环机制、调用栈以及任务队列

开发 开发工具 前端
在之前,我只是简单地认为由于函数执行很快,setTimeout执行时间即便为0也不会马上输出,而是等待函数执行完后再输出。实际上其运行机制就是js中的事件循环机制,在这个循环机制中呢,又与call Stack和task queue有关。

js里的事件循环机制十分有趣。从很多面试题也可以看出来,考察简单的setTimeout也就是考察这个机制的。

在之前,我只是简单地认为由于函数执行很快,setTimeout执行时间即便为0也不会马上输出,而是等待函数执行完后再输出。这只对了一半。

实际上其运行机制就是js中的事件循环机制,在这个循环机制中呢,又与call Stack和task queue有关。

[[190124]]

一、js事件循环机制

事件循环机制呢,简单点来说,就是在执行上下文的过程中,对函数的入栈和出栈。执行前函数先入栈,执行完后函数出栈。如若遇到了一些异步操作像回调函数以及ajax、setTimeout等,会先将他们交给浏览器的其他模块去执行,执行完后,会把回调函数放入到taskqueue中。当所有的call stack执行完后再开始执行task queue中的函数。

举一个简单的例子:

  1. console.log(1);  
  2. setTimeout(function() 

我们来看一下执行的内部过程

1. 执行***句,放入call stack中,输出 1

js事件循环机制

2. ***句出栈,执行第二句,由于是异步执行,交给其他模块。

js事件循环机制

3. 执行完后,将回调函数放入taskqueue中

js事件循环机制

4. 执行下一句,同***步一样,将语句入栈并执行,输出3

js事件循环机制

5. 语句出栈,此时call stack空了。开始执行task queue任务,输出2

js事件循环机制

所以,输出结果是

js事件循环机制

与预想一致。

二、进阶

如果添加了Promise又如何工作呢?

我们知道,Promise的回调函数不是传入的,而是使用then来调用的。因此,Promise中定义的函数应该是马上执行的,then才是其回调函数,放入queue队列中。

还提到了一个重要的概念:

  • macro-task包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
  • micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver

执行顺序:函数调用栈清空只剩全局执行上下文,然后开始执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次执行macro-task中的一个任务队列,执行完之后再执行所有的micro-task,就这样一直循环。

  1. (function test() {  
  2.     setTimeout(function() {console.log(4)}, 0);  
  3.     new Promise(function executor(resolve) {  
  4.         console.log(1);  
  5.         for( var i=0 ; i<10000 ; i++ ) {  
  6.             i == 9999 && resolve();  
  7.         }  
  8.         console.log(2);  
  9.     }).then(function() {  
  10.         console.log(5);  
  11.     });  
  12.     console.log(3);})() 

执行过程:

1. 遇到setTimeout,交给其他模块执行,执行完后回调放入macro-task中

2. 遇到Promise,立即执行里面的function,输出1。

3. 循环开始,遇到resolve(),修改Promise状态为fulfill。继续执行,输出2。

4. 遇到then,将回调放入micro-task中。

5. 继续执行,输出3。

6. call stack执行完毕了。开始执行micro-task中的回调函数,输出5。

7. micro-task执行完毕,开始执行macro-task中的回调函数,输出4。

8. 结束。

【本文为51CTO专栏作者“谢军”的原创稿件,转载可通过作者微信公众号(jingfeng18)获取联系】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2023-04-28 15:20:37

JavaScript事件循环

2021-07-24 11:15:19

开发技能代码

2021-01-18 08:24:51

JavaScriptMicrotask微任务

2020-12-29 08:21:03

JavaScript微任务宏任务

2021-12-24 16:55:44

前端开发JavaScript

2021-03-01 23:31:48

队列实现栈存储

2017-08-07 18:45:51

前端JavaScript技术栈

2017-07-26 13:51:19

前端JavaScriptTypeScript

2021-06-10 07:51:07

Node.js循环机制

2021-12-08 07:55:41

EventLoop浏览器事件

2022-08-11 08:03:43

队列

2022-06-13 10:24:47

宏任务微任务前端

2021-05-27 09:00:00

Node.js开发线程

2024-01-05 08:49:15

Node.js异步编程

2021-09-10 15:13:41

鸿蒙HarmonyOS应用

2017-08-16 10:36:10

JavaScriptNode.js事件驱动

2013-05-21 09:54:39

Web前端

2021-12-18 07:42:15

Ebpf 监控 Node.js

2015-03-26 13:14:53

javascriptjs callback实现调用

2022-09-21 12:01:22

消息队列任务队列任务调度
点赞
收藏

51CTO技术栈公众号