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

简介:

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

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

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

前端开发

一、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

相关文章
|
11天前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
18天前
|
JavaScript 安全 中间件
深入浅出Node.js中间件机制
【10月更文挑战第36天】在探索Node.js的奥秘之旅中,中间件的概念如同魔法一般,它让复杂的请求处理变得优雅而高效。本文将带你领略这一机制的魅力,从概念到实践,一步步揭示如何利用中间件简化和增强你的应用。
|
22天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
22天前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
29 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
27天前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
40 1
|
27天前
|
JavaScript 前端开发 开发者
JavaScript的事件循环
【10月更文挑战第27天】理解JavaScript的事件循环机制对于正确编写和理解JavaScript中的异步代码至关重要,它是JavaScript能够高效处理各种异步任务的关键所在。
33 1
|
28天前
|
JavaScript 前端开发 API
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第26天】前端技术的飞速发展让开发者在构建用户界面时有了更多选择。本文对比了Vue.js和Angular两大框架,介绍了它们的特点和优劣,并给出了在实际项目中如何选择的建议。Vue.js轻量级、易上手,适合小型项目;Angular结构化、功能强大,适合大型项目。
25 1
|
1月前
|
消息中间件 JavaScript 中间件
深入浅出Node.js中间件机制
【10月更文挑战第24天】在Node.js的世界里,中间件如同厨房中的调料,为后端服务增添风味。本文将带你走进Node.js的中间件机制,从基础概念到实际应用,一探究竟。通过生动的比喻和直观的代码示例,我们将一起解锁中间件的奥秘,让你轻松成为后端料理高手。
28 1
|
1月前
|
前端开发 JavaScript UED
"前端小技巧大揭秘:JS如何将后台时间戳秒变亲切小时前、分钟前,让用户秒懂,提升互动体验!"
【10月更文挑战第23天】在Web开发中,将后台返回的时间戳转换为“小时前”、“分钟前”、“刚刚”等友好的时间描述是常见需求。本文介绍如何用JavaScript实现这一功能,通过计算当前时间和时间戳的差值,返回相应的描述,提升用户体验。
30 1
|
2月前
|
前端开发 JavaScript 安全
JavaScript前端开发技术
JavaScript(简称JS)是一种广泛使用的脚本语言,特别在前端开发领域,它几乎成为了网页开发的标配。从简单的表单验证到复杂的单页应用(SPA),JavaScript都扮演着不可或缺的角色。
26 3