Event Loop 其实也就这点事

前段时间在网上陆续看了很多关于 Event loop 的文章,看完也就混个眼熟,可能内心深处对这种偏原理的知识有一些抵触心情,看完后也都没有去深入理解。最近在看 Vue 的源码,在读到关于 nextTick 的实现时,总有一种似曾相识的感觉,于是去网上查了下资料,原来 nextTick 的实现正是基于 Event loop 机制(引起重视了)。

Call Stack

众所周知,JavaScript 是 one-threaded,也就意味着在执行 JavaScript 的过程中,是 One thing at a time,而这样的特性,正是由一个叫 Call Stack 的东西决定的(有且仅有一个)。
既然是栈,就满足 FILO 的原则。故 Call Stack 在函数运行时的表现为:

  • 当有函数执行时,该函数被 push 到 Call Stack
  • 当函数执行结束时,该函数从 Call Stack 内被 pop 出
  • 如果函数内有调用到其他函数(执行结束前),则将其他函数再 push 到 Call Stack 中,等到调用结束时 pop 出

由此可见,如果一个函数定义如下:

const dead = () => {return dead();
}

那么当其被执行时,就会向 Call Stack 中不断的 push 同一个函数(dead),导致整个页面挂掉。

When Call Stack Meets Sync Request

众所又周知了,在 jQuery 提供的 Ajax 函数中,可供开发者选择请求是 sync 还是 async,我们先讨论 Call Stack 遇到 sync 请求时会发生什么。

const name = $.ajaxSync(URL_1);
const info = $.ajaxSync(URL_2);
const work = $.ajaxSync(URL_3);console.log(name);
console.log(info);
console.log(work);

屋漏偏逢连阴雨,此时的网络状态又极差,每一个网络请求从发出到成功要经历五秒,想象一下上面这段代码如果跑起来了,会发生什么?
这是一件让人绝望的事情:
随着程序的推进,ajaxSync 函数会先后三次被 push 并 pop 出 Call Stack,而每一次从 push 到 pop 的过程需要耗费五秒钟的时间。
无论从工程效率还是用户体验的角度来说,这都是不被允许的一件事情。

Async & Callback

为了杜绝上面的问题,浏览器提供给了开发者一个叫做异步 Callback 的解决方案。先看一段代码:

console.log('kyrieliu');setTimeout(function(){console.log('about Event Loop');
}, 5000);console.log(' is writing an article ');

运行结果显而易见。
ok,那么这段代码在 Call Stack 中的表现又是怎样的呢?
基于上面文章所述,我推测:
首先,第一行代码入栈,执行完毕后出栈;紧接着,setTimeout 入栈,然后emmm,事情有点不对劲了:如果 setTimeout 入栈执行后立刻出栈,那么它内部的 console 为什么五秒后才打印出来?

Task Queue

问题的关键,是一个叫做 Task Queue 的东西。
紧接着刚才的步骤:setTimeout入栈后执行并触发了一个五秒的 timer,这个 timer 由 Web api 维护,至此,setTimeout执行完毕并出栈,第三个 console 入栈执行并出栈。五秒后,timer 结束计时,将回调函数 callback 下放到 task queue 中。
但 callback 还未执行,它什么时候执行呢?Call Stack 为空的时候。
此时的 call stack 已经为空,所以 callback 被 push 进栈执行并 pop 出,这样一来就解释得通了。 至此,正式引出 Event Loop 的概念。

Event Loop

If the call stack is clear and there's something in the task queue, push the first thing on the queue onto the stack.

setTimeout(callback, 0)

在最开始接触 JavaScript 的时候,看到上面这行代码的我是懵蔽的,0ms 后执行 callback, WTF?
在了解了 Event Loop 的运行机制后,再回过头来尝试解释一下这行代码,即:在 setTimeout 入栈执行时,内部的 callback 会立即被下放到 task queue 中,但它无法执行,因为此时的 call stack 不为空,等到 call stack 为空时,callback 才得以执行。

Thanks

  • Philip Roberts: Help, I’m stuck in an event-loop.
  • A super-cool demo of Event Loop

广而告之

个人公众号,不止于前端

个人公众号:劉凯里

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mock模拟接口测试 vue_在 Vue-CLI 中引入 simple-mock实现简易的 API Mock 接口数据模拟...

在 https://www.jb51.net/article/151520.htm这篇文章中,我们介绍了在 Angular-CLI 中引入 simple-mock 的方法。本文以 Vue-CLI 为例介绍引入 simple-mock 实现前端开发数据模拟的步骤。本质上这里介绍的是在 webpack-dev-server 中配置 simple-mock 实现 API Mock…

Kudu系列: Kudu主键选择策略

每个Kudu 表必须设置Pimary Key(unique), 另外Kudu表不能设置secondary index, 经过实际性能测试, 本文给出了选择Kudu主键的几个策略, 测试结果纠正了我之前的习惯认知. 简单介绍测试场景: 表中有一个unqiue字段Id, 另外还有一个日期维度字段histdate, 有三种设置kudu PK的方法…

OSS网页上传和断点续传(OSS配置篇)

OSS网页上传和断点续传主要根据BrowserJS-SDK和相关文档整理而得,快速构建OSS上传应用 一、Bucket设置 浏览器中直接访问OSS需要开通Bucket的CORS设置 将allowed origins设置成 *将allowed methods设置成 PUT, GET, POST, DELETE, HEAD将allowed headers设置成 *将e…

html vbs 输入框,HTML_vbs实现的下拉框对应键入值,vbs实现的下拉框对应键入值 - phpStudy...

vbs实现的下拉框对应键入值vbs实现的下拉框对应键入值 选择自 gu1dai 的 Blog关键字 vbs实现的下拉框对应键入值select centerbody{text-align:left;font:12px #000080 ;}#main{float:left;width:750px;border:#dddddd 1px solid;margin:5px 10px;padding:10px 5px;}#maintable…

为您的下一个基于Spring的应用程序考虑使用spring-boot的原因!

Spring-boot提供了一种创建基于Spring的应用程序的快速方法。 对于下一个项目,有一些非常令人信服的理由考虑使用Spring-boot: 原因1:使用spring-boot启动程序项目进行更简单的依赖性管理。 考虑使用Spring引导提供数据访问抽象的h2数据库实…

小程序各种姿势实现登录

喜闻乐见的背景时间--由于最近接触小程序比较多,又刚好经历过小程序的自动登录时代以及现在的点击登录时代。结合自己的实践以及观察到其他小程序的做法,就有了这篇小分享~ 本文可能涉及的内容-- 更新 首先感谢shaonialife同学的精彩评论~ 可能由于用词…

c#如何使用反射去创建一个委托_C# 反射的委托创建器

.Net 的反射是个很好很强大的东西,不过它的效率却实在是不给力。已经有很多人针对这个问题讨论过了,包括各种各样的 DynamicMethod 和各种各样的效率测试,不过总的来说解决方案就是利用 Expression Tree、Delegate.CreateDelegate 或者 Emit …

BBS-登录

from django.db import models# Create your models here. from django.contrib.auth.models import AbstractUser#用户 class UserInfo(AbstractUser):nidmodels.AutoField(primary_keyTrue)telephonemodels.CharField(max_length32)avatarmodels.FileField(upload_toavatar/,…

html 输入框从左上角,在输入框的左上角,使文本开始_input_开发99编程知识库

網頁上有幾個輸入框,我希望文本從左上角開始。 目前,使用 below,它的左對齊,但在框的中間。 我嘗試了垂直對齊和其他的東西,但沒有。 我不想使用 padding,因為文本需要包圍,它只能使它彈出框頂部…

PHP定时任务Crontab结合CLI模式详解

从版本 4.3.0 开始,PHP 提供了一种新类型的 CLI SAPI(Server Application Programming Interface,服务端应用编程端口)支持,名为 CLI,意为 Command Line Interface,即命令行接口。 STDIN 标准输…

使用Mockito和BeanPostProcessors在Spring注入测试双打

我非常确定,如果您曾经使用过Spring并且熟悉单元测试,那么您会遇到与您不想修改的Spring应用程序上下文中注入模拟/间谍(测试双打)有关的问题。 本文介绍了一种使用Spring组件解决此问题的方法。 项目结构 让我们从项目结构开始&…

当面试官问你如何进行性能优化时,你该这么回答(一)

背景 在开发好页面后,如何让页面更快更好的运行,是区分一个程序猿技术水平和视野的一个重要指标。所以面试时,面试官总会问你一个问题,如何进行性能优化呢? 如果你这时是头脑一片空白,或是像之前的我一样…

二叉搜索时与双向链表python_JZ26-二叉搜索树与双向链表

1、中序遍历,当前结点,以及左侧排好序的双向链表,再调整当前结点的指针指向最前结点/* struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;TreeNode(int x) :val(x), left(NULL), right(NULL) {} };*/ class Solution …

dva使用心得

组件在异步数据到来前已经完成初始化&#xff0c;是导致constructor中无法取到所需数据的原因。所以最直接的方法&#xff0c;就是修改组件创建的时间 //把原来的组件内部控制显示/* <ComponentName show{modelName.show}/> *///更改为状态直接控制组件是否存在{ modelN…

html右缩进怎么设置,WPS中怎么设置右缩进两个字符?

回答&#xff1a;打开我们的Word文档&#xff0c;调整好我们的文字内容&#xff0c;然后全选我们的文字内容&#xff0c;注意要分段时按下键盘上的回车键另起一行。请点击输入图片描述接着&#xff0c;我们点击顶部菜单栏的“开始”菜单&#xff0c;在开始菜单下面的子菜单中找…

VS2013专业版+QT5.6.3+qt-vs-addin-1.2.5环境搭建

一、工具资料&#xff1a; 1.vs2013专业版地址&#xff1a;http://download.csdn.net/download/u010368556/10238145 2.qt各版本地址&#xff1a;http://download.qt.io/archive/qt/ 3.qt-vs插件地址&#xff1a;http://download.qt.io/archive/vsaddin/ 二、环境搭建过程&…

不到50行代码实现一个能对请求并发数做限制的通用RequestDecorator

使用场景 在开发中&#xff0c;我们可能会遇到一些对异步请求数做并发量限制的场景&#xff0c;比如说微信小程序的request并发最多为5个&#xff0c;又或者我们需要做一些批量处理的工作&#xff0c;可是我们又不想同时对服务器发出太多请求&#xff08;可能会对服务器造成比…

使用ActiveMQ和HornetQ通过WebSocket通过STOMP轻松进行消息传递

消息传递是用于构建不同级别的分布式软件系统的极其强大的工具。 通常&#xff0c;至少在Java生态系统中&#xff0c;客户端&#xff08;前端&#xff09;从不直接与消息代理&#xff08;或交换&#xff09;进行交互&#xff0c;而是通过调用服务器端&#xff08;后端&#xff…

yum 安装mysql的位置_Yum安装MySQL以及相关目录路径和修改目录

有些时候,为了方便,有些同学喜欢通过yum的方式安装MySQL,没有设置统一的文件目录以及软件目录,那么就会为后续的维护工作带来很大的麻烦&#xff01;下面就简单介绍一下yum安装MySQL的步骤以及这类安装下的相关目录路径,最后简单介绍下如何更改文件目录&#xff01;YUM安装MySQ…

【laravel】【转发】laravel 导入导出excel文档

1、简介 Laravel Excel 在 Laravel 5 中集成 PHPOffice 套件中的 PHPExcel &#xff0c;从而方便我们以优雅的、富有表现力的代码实现Excel/CSV文件的导入和 导出 。 该项目的GitHub地址是&#xff1a; https://github.com/Maatwebsite/Laravel-Excel 。 本文我们将在Laravel中…