javascript基础修炼(5)—Event Loop(Node.js)

时间:2022-08-26 13:29:35

开发者的javascript造诣取决于对【动态】和【异步】这两个词的理解水平。

javascript基础修炼(5)—Event Loop(Node.js)

一. 一道考察异步知识的面试题

题目是这样的,要求写出下面代码的输出:

setTimeout(() => {
console.log(1)
}, 0)
new Promise((resolve, reject) => {
console.log(2)
for (let i = 0; i < 10000; i++) {
i === 9999 && resolve()
}
console.log(3)
}).then(() => {
console.log(4)
})
console.log(5)

如果没有详细钻研过异步队列,答对的可能性很低。题目的考察点很明确,就是javascript中最核心的特点之一的【异步】,了解了原理以后,你就会明白javascript中声称的“无阻塞”并不是完全成立的,通过一些小办法就可以让setTimeout( )的回调永远都无法被执行,尽管这看起来除了满足整蛊需求以外并没有什么明显的实用价值。

对Event Loop的理解,带给开发者的是对代码整个生命周期更精细的控制能力,尽管在依赖于SPA框架的开发中你几乎不会用到它们。

二. Event Loop的原理

javascript基础修炼(5)—Event Loop(Node.js)

(上图来自下面推荐的这篇博文)

【极力推荐文章】

https://github.com/nswbmw/node-in-debugging/blob/master/3.6 Event Loop.md

并不是笔者偷懒不想写这一节,而是在读过了这篇教程以后,自认为除非是剖析更底层的libuv的原理,否则仅就理解Event Loop而言,笔者自己认为不会比这篇写的清晰。

三. 解析最后一题

上文中给出了从简单到复杂共6道题来供读者自检,算是非常贴心了,本文中针对最后一题进行一些讲解。你会发现只要理解了Event Loop 的基本原理后,分析这类代码基本就是一个【完形填空】的过程

题目如下:

setImmediate(() => {
console.log(1)
setTimeout(() => {
console.log(2)
}, 100)
setImmediate(() => {
console.log(3)
})
process.nextTick(() => {
console.log(4)
})
})
process.nextTick(() => {
console.log(5)
setTimeout(() => {
console.log(6)
}, 100)
setImmediate(() => {
console.log(7)
})
process.nextTick(() => {
console.log(8)
})
})
console.log(9)

题目分析:

为了方便分析,先做代码分块:

javascript基础修炼(5)—Event Loop(Node.js)

将代码块放入事件循环:

javascript基础修炼(5)—Event Loop(Node.js)

分析:

这里有必要说明一下Fn2的位置,文中并没有明确提及同步代码执行完毕后进入异步队列时会先经历Tick阶段,就图示而言,每一个宏观任务阶段之间都会检查Tick队列(你也可以理解为每次函数的调用栈被清空的时候会检查一次Tick队列),那么Fn2的待执行时序也就很好理解了。为了方便分析,将console.log(n)相关的方法称为cln

接下来看一下当执行至Fn2时发生的事情:

javascript基础修炼(5)—Event Loop(Node.js)

分析:

Tick队列中的process.nextTick( )回调会直接加入Tick队列(此处就可以实现篇头讲到的阻塞事件循环)。另外讲一下CL6这个回调,它上面绑定了一个100ms的定时器,在后续的TimersIO Polling中都会检查倒计时是否到期,到了就执行,没到就等下一次TimersIO Polling阶段再检查。从上例来看,推迟100ms的CL6在没有其他干扰的情况下几乎一定会在N个event loop以后才被执行。

同样的道理来拆分一下Fn1:

javascript基础修炼(5)—Event Loop(Node.js)

分析:

CL6CL2先开始计时,所以倒计时100ms先到,当然这是N个事件循环以后的事情了。

所以从上面的时序就可以看到输出的结果:9 5 8 1 7 4 3 6 2

【思考题】:

外加一个思考题,如果上例中CL6CL2的延迟都是0,结果是怎样的呢?

四. requestAnimationFrame

requestAnimationFrame() 很多时候会被拿来和setTimeout()作对比,这个API是浏览器环境下为了实现高性能帧动画而设计的,它的主要目的是为了让浏览器的重绘能够配合显示设备的刷新率而去掉不必要的性能开销,常见的显示设备刷新率为60Hz,相当于你每1000/60≈16.7ms只能看屏幕一眼,得到的信息都是依靠这些离散画面的视觉暂留拼凑起来的,那如果动画元素在你看屏幕的时间间隔中像素位移过大的话,看起来就会是一卡一卡的,也就是平时常说的“丢帧”,从Event Loop的角度来讲的话,将其近似理解为setTimeout(fn, 1000/刷新率)就可以了。

编辑/寻水的鱼

本文首发于华为云社区:原文链接

javascript基础修炼(5)—Event Loop(Node.js)的更多相关文章

  1. javascript基础修炼&lpar;7&rpar;——Promise,异步,可靠性

    开发者的javascript造诣取决于对[动态]和[异步]这两个词的理解水平. 一. 别人是开发者,你也是 Promise技术是[javascript异步编程]这个话题中非常重要的,它一度让我感到熟悉 ...

  2. JavaScript 运行机制以及Event Loop(事件循环)

    一.JavaScript单线程 众所周知JavaScript是一门单线程语言,也就是说,在同一时间内JS只能做一件事.为什么JavaScript不能有多个线程呢?这样不是能够提高效率吗? JavaSc ...

  3. Node&period;js event loop 和 JS 浏览器环境下的事件循环的区别

    Node.js  event loop 和 JS 浏览器环境下的事件循环的区别: 1.线程与进程: JS 是单线程执行的,指的是一个进程里只有一个主线程,那到底什么是线程?什么是进程? 进程是 CPU ...

  4. javascript基础修炼&lpar;4&rpar;——UMD规范的代码推演

    javascript基础修炼(4)--UMD规范的代码推演 1. UMD规范 地址:https://github.com/umdjs/umd UMD规范,就是所有规范里长得最丑的那个,没有之一!!!它 ...

  5. javascript基础修炼&lpar;11&rpar;——DOM-DIFF的实现

    目录 一. 再谈从Virtual-Dom生成真实DOM 二. DOM-Diff的目的 三. DOM-Diff的基本算法描述 四. DOM-Diff的简单实现 4.1 期望效果 4.2 DOM-Diff ...

  6. 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制&lpar;event loop&rpar;

    JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...

  7. JavaScript、jQuery、HTML5、Node&period;js实例大全-读书笔记2

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] JavaScript.jQuer ...

  8. JavaScript、jQuery、HTML5、Node&period;js实例大全-读书笔记1

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] 第 3 章 用 JavaScri ...

  9. javascript基础修炼&lpar;2&rpar;——What&&num;39&semi;s this&lpar;上&rpar;

    目录 一.this是什么 二.近距离看this 三. this的一般指向规则 四. 基本规则示例 五. 后记 开发者的javascript造诣取决于对[动态]和[异步]这两个词的理解水平. 一.thi ...

随机推荐

  1. angular路由——ui&period;route

    angular路由 使用案例 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  2. CSS 中如何把 Span 标签设置为固定宽度

    一.形如<span>ABC</span>独立行设置SPAN为固定宽度方法如下: span {width:60px; text-align:center; display:blo ...

  3. 立体透视 perspective transform-style 倾斜旋转

    1.perspective 是设置镜头距离,距离越远视图越小,视图越近,视图越大.就像相机焦距一样.其只对子元素产生效果. 2.transform-style: preserve-3d 设置3d效果, ...

  4. 分布式消息队列kafka系列介绍 — 核心API介绍及实例

    原文地址:http://www.inter12.org/archives/834 一 PRODUCER的API 1.Producer的创建,依赖于ProducerConfig public Produ ...

  5. openshift云计算平台diy模式安装Python2&period;7&plus;Flask

    主要翻译了链接1)的教程,加上一些个人研究,步骤如下: 1) 在openshift.redhat.com申请账号,安装git for windows,然后安装gem install rhc,这些比较容 ...

  6. python - 沙盒环境 - virtualenv - 简明使用录

    1. 不讲安装,没意思 2. 使用 virtualenv ENV # 建立环境,ENV你可以随便定,看起来像是 mkdir ENV cd ENV # 进目录呗 source bin/activate ...

  7. 关于Java获取系统信息

    本文部分转载自: http://www.cnblogs.com/wuhenke/archive/2011/11/19/2255400.html 我总结的相关类似博客:http://www.cnblog ...

  8. Debian9 使用 Docker 安装 gitlab完整过程

    一. 安装Docker CE (参考 官网指南) 1. 卸载老版本 sudo apt-get remove docker docker-engine docker.io  2. Update the ...

  9. 总结and规划

    不知不觉中又过去了一年,马上就要读研究生了,因此有必要对自己进行必要的总结,以及对自己有个良好的规划. 首先,描述自己当前的心情——对未来充满了恐惧和焦虑. 马上大学就要毕业了,回首经历的大学生涯,似 ...

  10. 廉价的SUP掌机拆解

    最近经常出现的一款山寨sup掌机, 75元包邮入手, 全套配件如下. 看看正面和背面的实拍图, 比较明显的廉价玩具塑料感. 手柄和充电线共用下方的microUSB口, 所以在双打时是不能用电源供电的. ...