node.js中对Event Loop事件循环的理解与应用实例分析


Posted in Javascript onFebruary 14, 2020

本文实例讲述了node.js中对Event Loop事件循环的理解与应用。分享给大家供大家参考,具体如下:

javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务。

同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行。

异步任务是不进入主线程,而是进入一个 "任务队列" 里,"任务队列" 通知主线程,该异步任务才会进入主线程执行。

任务的运行机制如下:

1、所有同步任务在主线程上执行,形成一个 "执行栈",注意栈是先进后出的。

2、主线程外,有一个 "任务队列" ,只要异步任务处理完有结果了,就在 "任务队列" 中放置一个事件,注意队列是先进先出的。

3、一旦 "执行栈" 中所有同步任务执行完毕。系统读取 "任务队列" 中的事件,对应的异步任务。放入 "执行栈" 中,开始执行。

4、主线程不断重复第三步,这种循环从 "任务队列" 中读取事件处理的这种运行机制称为Event Loop(事件循环)。

"执行栈" 中的同步代码总是比 "任务队列"中的异步任务之前运行。

function fun() {
  setTimeout(function () {
    console.log('异步任务');
  }, 0);
  console.log(1);
  console.log(2);
  console.log(3);
  console.log(4);
  console.log(5);
}
fun();

上面的代码,console.log代码写在setTimeout后面,但仍然先执行。

"任务队列" 是一个队列,队列的特性是先进先出。看下面代码:

function fun() {
  console.log(1);
  setTimeout(function () {
    console.log(2);
    setTimeout(function () {
      console.log(3);
    }, 0);
  }, 0);
  console.log(4);
}
fun();

输出结果为 1  4  2  3,打印 2 的setTimeout任务比打印 3 的setTimeout任务先进入队列,所以会先运行。

对于异步操作,像ajax,只有操作成功后返回结果,才会进入 "任务队列" 中,而不是调用的时候就放入队列中。看下面代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script>
  function ajax() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://mail.163.com/', true);
    xhr.send();
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        console.log(xhr.responseText);
      }
    };
  }
  function fun() {
    console.log(1);
    ajax();
    setTimeout(function () {
      console.log(2);
    }, 1000);
    console.log(3);
  }
  fun();
</script>
</body>
</html>

ajax() 与 setTimeout 谁先进入队列,谁先输出,是需要看两者消耗时间,谁更短。时间短的会先进入队列先运行。

setTimeout 与 setInterval 运行机制一样,都是在指定时间把事件插入到 "任务队列" 尾部。区别是前者只执行一次,后者可反复执行。

node.js 还为我们提供了,process.nextTick 和 setImmediate 与 "任务队列" 有关的方法。

process.nextTick 会把回调函数放在当前 "执行栈" 的尾部。也就是说是在读取 "任务队列" 之前运行。

function fun() {
  console.log(1);
  setTimeout(function () {
    console.log(2);
  }, 0);
  process.nextTick(function () {
    console.log(3);
    process.nextTick(function () {
      console.log(4);
    });
  });
  process.nextTick(function () {
    console.log(5);
  });
  console.log(6);
}
fun();

上面的代码会输出 1  6  3  5  4  2 ,注意process.nextTick会把回调函数放在 "执行栈" 的尾部。

同步代码最先输出 1  6,然后 3 的先放入尾部,然后 5 的跟在 3 后面。3先执行,然后把 4 放入到 5 的后面。5执行完后,再执行4,最后读取 "任务队列" 中的输出2。

setImmediate 会把回调函数放在当前 "任务队列" 的尾部。也就是下一次事件循环Event Loop时执行。

function fun() {
  console.log(1);
  setTimeout(function () {
    console.log(2);
  }, 0);
  setImmediate(function () {
    console.log(3);
  });
  console.log(4);
}
fun();

上面的代码是会输出 1  4  2  3 还是 1  4  3  2 是不确定的,因为setTimeout 与 setImmediate 都会在下一次事件循环Event Loop中触发,所以输出是不确定的。

希望本文所述对大家node.js程序设计有所帮助。

Javascript 相关文章推荐
浅析tr的隐藏和显示问题
Mar 05 Javascript
javascript性能优化之DOM交互操作实例分析
Dec 12 Javascript
jquery跟随屏幕滚动效果的实现代码
Apr 13 Javascript
jQuery stop()用法实例详解
Jul 28 Javascript
基于iscroll.js实现下拉刷新和上拉加载效果
Nov 28 Javascript
Jquery on绑定的事件 触发多次实例代码
Dec 08 Javascript
VueJs单页应用实现微信网页授权及微信分享功能示例
Jul 26 Javascript
vue mintui-Loadmore结合实现下拉刷新和上拉加载示例
Oct 12 Javascript
微信小程序实现animation动画
Jan 26 Javascript
jQuery实现的点击显示隐藏下拉菜单功能完整示例
May 17 jQuery
cordova+vue+webapp使用html5获取地理位置的方法
Jul 06 Javascript
js将日期格式转换为YYYY-MM-DD HH:MM:SS
Sep 18 Javascript
Angular之jwt令牌身份验证的实现
Feb 14 #Javascript
node.js中module模块的功能理解与用法实例分析
Feb 14 #Javascript
JS实现简易计算器
Feb 14 #Javascript
vue vantUI tab切换时 list组件不触发load事件的问题及解决方法
Feb 14 #Javascript
node.js中npm包管理工具用法分析
Feb 14 #Javascript
vue-cli创建的项目中的gitHooks原理解析
Feb 14 #Javascript
基于vue的tab-list类目切换商品列表组件的示例代码
Feb 14 #Javascript
You might like
php.ini中的php-5.2.0配置指令详解
2008/03/27 PHP
浅谈PHP中output_buffering
2015/07/13 PHP
PHP基于单例模式编写PDO类的方法
2016/09/13 PHP
Laravel 将数据表的数据导出,并生成seeds种子文件的方法
2019/10/09 PHP
通过JAVASCRIPT读取ASP设定的COOKIE
2007/02/15 Javascript
幻灯片带网页设计中的20个奇妙应用示例小结
2012/05/27 Javascript
jQuery表单获取和失去焦点输入框提示效果的实例代码
2013/08/01 Javascript
浅析Cookie中的Path与domain
2013/12/18 Javascript
jquery选择器之内容过滤选择器详解
2014/01/27 Javascript
jQuery 中DOM 操作详解
2015/01/13 Javascript
javascript数组去重的方法汇总
2015/04/14 Javascript
利用JS判断鼠标移入元素的方向
2016/12/11 Javascript
浅谈javascript中的数据类型转换
2016/12/27 Javascript
超简单的Vue.js环境搭建教程
2017/03/17 Javascript
node使用UEditor富文本编辑器的方法实例
2017/07/11 Javascript
Vue.js 实现微信公众号菜单编辑器功能(一)
2018/05/08 Javascript
vue中keep-alive、activated的探讨和使用详解
2020/07/26 Javascript
Python的Flask框架中实现分页功能的教程
2015/04/20 Python
python使用matplotlib绘制柱状图教程
2017/02/08 Python
tensorflow: 查看 tensor详细数值方法
2018/06/13 Python
python中使用 xlwt 操作excel的常见方法与问题
2019/01/13 Python
详解【python】str与json类型转换
2019/04/29 Python
python 叠加等边三角形的绘制的实现
2019/08/14 Python
python调用c++返回带成员指针的类指针实例
2019/12/12 Python
python实现超级玛丽游戏
2020/03/18 Python
Python中生成ndarray实例讲解
2021/02/22 Python
土耳其新趋势女装购物网站:Addax
2020/01/07 全球购物
幼儿园教师节活动方案
2014/02/02 职场文书
电大本科自我鉴定
2014/02/05 职场文书
中国好声音华少广告词
2014/03/17 职场文书
优秀少先队工作者事迹材料
2014/05/13 职场文书
物理系毕业生自荐书
2014/06/13 职场文书
财务经理岗位职责
2015/01/31 职场文书
2015秋季新学期开学寄语
2015/05/28 职场文书
教师节祝酒词
2015/08/11 职场文书
vue组件冲突之引用另一个组件出现组件不显示的问题
2022/04/13 Vue.js