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 相关文章推荐
Dom 学习总结以及实例的使用介绍
Apr 24 Javascript
JavaScrip实现PHP print_r的数功能(三种方法)
Nov 12 Javascript
用JavaScript实现页面重定向功能的教程
Jun 04 Javascript
再JavaScript的jQuery库中编写动画效果的指南
Aug 13 Javascript
详解JavaScript的闭包、IIFE、apply、函数与对象
Dec 21 Javascript
微信小程序页面传值实例分析
Apr 19 Javascript
简单谈谈require模块化jquery和angular的问题
Jun 23 jQuery
vue实现点击隐藏与显示实例分享
Feb 13 Javascript
纯javascript实现选择框的全选与反选功能
Apr 08 Javascript
jQuery控制input只能输入数字和两位小数的方法
May 16 jQuery
JavaScript 自定义html元素鼠标右键菜单功能
Dec 02 Javascript
Js利用正则表达式去除字符串的中括号
Nov 23 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
德生PL450的电路分析和低放电路的改进办法
2021/03/02 无线电
用C/C++扩展你的PHP 为你的php增加功能
2012/09/06 PHP
PHP获取一年中每个星期的开始和结束日期的方法
2015/02/12 PHP
CodeIgniter框架常见用法工作总结
2017/03/16 PHP
Redis构建分布式锁
2017/03/28 PHP
PHP使用PDO 连接与连接管理操作实例分析
2020/04/21 PHP
IE 条件注释详解总结(附实例代码)
2009/08/29 Javascript
EasyUi tabs的高度与宽度根据IE窗口的变化自适应代码
2010/10/26 Javascript
JS获取单击按钮单元格所在行的信息
2014/06/17 Javascript
理解javascript中的原型和原型链
2015/07/30 Javascript
jQuery遮罩层实现方法实例详解(附遮罩层插件)
2015/12/08 Javascript
jquery+css3实现会动的小圆圈效果
2016/01/27 Javascript
jQuery Ajax File Upload实例源码
2016/12/12 Javascript
微信小程序动态的加载数据实例代码
2017/04/14 Javascript
Vue自定义事件(详解)
2017/08/19 Javascript
layui 选择列表,打勾,点击确定返回数据的例子
2019/09/02 Javascript
javascript递归函数定义和用法示例分析
2020/07/22 Javascript
Python深入学习之装饰器
2014/08/31 Python
Python中使用MELIAE分析程序内存占用实例
2015/02/18 Python
Python合并字符串的3种方法
2015/05/21 Python
python获得文件创建时间和修改时间的方法
2015/06/30 Python
Python中的数据对象持久化存储模块pickle的使用示例
2016/03/03 Python
python如何查看系统网络流量的信息
2016/09/12 Python
浅谈python中的占位符
2017/11/09 Python
Django项目中model的数据处理以及页面交互方法
2018/05/30 Python
python实现键盘输入的实操方法
2019/07/16 Python
python字符串反转的四种方法详解
2019/12/02 Python
Python实现遗传算法(二进制编码)求函数最优值方式
2020/02/11 Python
详解Python中的文件操作
2021/01/14 Python
携程旅行网:中国领先的在线旅行服务公司
2017/02/17 全球购物
Seavenger官网:潜水服、浮潜、靴子和袜子
2020/03/05 全球购物
UNOde50美国官网:西班牙珠宝品牌
2020/08/15 全球购物
几个Shell Script面试题
2012/08/31 面试题
教师党的群众路线学习心得体会
2014/11/04 职场文书
导游词之青岛太清宫
2019/12/13 职场文书
redis内存空间效率问题的深入探究
2021/05/17 Redis