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,一经查实,立即删除!

相关文章

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…

小程序各种姿势实现登录

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

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/,…

使用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 …

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

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

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

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

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

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

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

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

你真的了解css像素嘛?

在日常开发中,px一定是大家接触过最多的css单位,但是你真的了解px嘛?1px在屏幕中到底是多大呢?另外不知道大家有没有过下面这些疑惑: 为什么一个元素在pc上和移动端的物理尺寸不一样,但是两者的视觉效果上却差不多呢&…

mysql for mac中文_mysql for Mac 下创建数据表中文显示为?的解决方法

在我的绝版Mac mini下安装了mysql 5.7版本,实例中,在通过load data 导入数据时发现表中的中文显示为 ?通过百度,发现多个版本的解决方法,将其中一个成功解决的方法贴上来:大多方法都是这样:需要…

计算机科学计算方面分为,计算机方面的专业分为哪些类?【资讯与计算科学】和【电脑科学与技术专业】有什么不同?...

计算机方面的专业分为哪些类?【资讯与计算科学】和【电脑科学与技术专业】有什么不同?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!计算机方面的专业分为哪些类&am…

Java异常处理教程(包含示例和最佳实践)

异常是可能在程序执行期间发生的错误事件,它会破坏其正常流程。 Java提供了一种健壮且面向对象的方式来处理异常情况,称为Java异常处理 。 我们将在本教程中研究以下主题。 Java异常处理概述 异常处理关键字 异常层次 有用的异常方法 Java 7自动资源…

GMTC 大前端时代前端监控的最佳实践

本文来自阿里云前端监控团队,转载请注明出处本文为2018年6月21日,在北京举办的GMTC(全球大前端技术大会),下午性能与监控专场,由阿里云前端监控团队前端技术专家彭伟春带来的演讲稿,现场反馈效果非常好,地上…

Alpha阶段敏捷冲刺②

1.提供当天站立式会议照片一张 每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作。 购买云服务器 注册账号 界面布局初步规划 今天计划完成的工作。 界面雏形设计 数据库初步设计 完成后端框架初步…

透明地持久保存并从数据库中检索加密的数据

自从我在这里发表上一个帖子以来已经有两个多月了,但是今年六月和七月非常忙碌而密集。 首先, Confitura的组织(欧洲最大的Java开发人员免费会议)参加了我所有的免费晚会,然后在相当紧张的住院期间,我们的第…

[译] 2017 年比较 Angular、React、Vue 三剑客

原文地址:Angular vs. React vs. Vue: A 2017 comparison原文作者:Jens Neuhaus译文出自:掘金翻译计划本文永久链接:https://github.com/xitu/gold-miner/blob/master/TODO/angular-vs-react-vs-vue-a-2017-comparison.md译者&…

centos 离线安装mysql_CentOS6离线安装mysql-5.7.25

1.mysql-5.7.25-1.el6.x86_64.rpm-bundle.tar下载百度云资源提取码:ej1y2.把下载的mysql安装包上传到Centos上解压mysql,我这是在Windows上解压的上传到Centos上,我在Centos上解压mysql不知道为什么少了rpm -ivh mysql-community-common-5.7.…

Linux自动化之Cobbler补鞋匠安装

cobbler介绍: 快速网络安装linux操作系统的服务,支持众多的Linux发行版:Red Hat、 Fedora、CentOS、Debian、Ubuntu和SuSE,也可以支持网络安装windows PXE的二次封装,将多种安装参数封装到一个菜单 Python编…