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 相关文章推荐
javascript 字符 Escape,encodeURI,encodeURIComponent
Jul 09 Javascript
Jquery uploadify上传插件使用详解
Jan 13 Javascript
js创建jsonArray传输至后台及后台全面解析
Apr 11 Javascript
基于jPlayer三分屏的制作方法
Dec 21 Javascript
jQuery源码解读之extend()与工具方法、实例方法详解
Mar 30 jQuery
关于ES6箭头函数中的this问题
Feb 27 Javascript
ECharts地图绘制和钻取简易接口详解
Jul 12 Javascript
Vue中对iframe实现keep alive无刷新的方法
Jul 23 Javascript
关于layui的动态图标不显示的解决方法
Sep 04 Javascript
详解一些适用于Node.js的命名约定
Dec 08 Javascript
nuxt.js服务端渲染中axios和proxy代理的配置操作
Nov 06 Javascript
js动态添加带圆圈序号列表的实例代码
Feb 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 上传文件类型判断函数(避免上传漏洞 )
2010/06/08 PHP
php 阴历-农历-转换类代码
2012/01/16 PHP
php文件夹的创建与删除方法
2015/01/24 PHP
浅谈PHP中JSON数据操作
2015/07/01 PHP
PHP MYSQL简易交互式站点开发
2016/12/27 PHP
thinkPHP5框架分页样式类完整示例
2018/09/01 PHP
PHP调用全国天气预报数据接口查询天气示例
2019/02/20 PHP
利用javascript查看html源文件
2006/11/08 Javascript
jquery表单验证使用插件formValidator
2012/11/10 Javascript
JS将表单导出成EXCEL的实例代码
2013/11/11 Javascript
node.js中的url.resolve方法使用说明
2014/12/10 Javascript
js实现仿百度瀑布流的方法
2015/02/05 Javascript
javascript关于运动的各种问题经典总结
2015/04/27 Javascript
使用AngularJS来实现HTML页面嵌套的方法
2015/06/17 Javascript
基于Jquery代码实现支持PC端手机端幻灯片代码
2015/11/17 Javascript
JavaScript实现页面定时刷新(定时器,meta)
2016/10/12 Javascript
node.js基于fs模块对系统文件及目录进行读写操作的方法详解
2017/11/10 Javascript
微信小程序textarea层级过高(盖住其他元素)问题的解决办法
2019/03/04 Javascript
Layui 动态禁止select下拉的例子
2019/09/03 Javascript
记一次react前端项目打包优化的方法
2020/03/30 Javascript
[08:08]2014DOTA2国际邀请赛中国区预选赛精彩TOPPLAY
2014/06/25 DOTA
python判断windows隐藏文件的方法
2014/03/21 Python
python多任务及返回值的处理方法
2019/01/22 Python
Python类成员继承重写的实现
2020/09/16 Python
CSS3中动画属性transform、transition和animation属性的区别
2016/09/25 HTML / CSS
会话Bean的种类
2013/11/07 面试题
三年大学自我鉴定
2014/01/16 职场文书
本科生职业生涯规划书范文
2014/01/21 职场文书
教师年度考核评语
2014/04/28 职场文书
小学亲子活动总结
2014/07/01 职场文书
学校节能宣传周活动总结
2014/07/09 职场文书
2015年社区综治工作总结
2015/04/21 职场文书
员工规章制度范本
2015/08/07 职场文书
和领导吃饭祝酒词
2015/08/11 职场文书
《秦兵马俑》教学反思
2016/02/24 职场文书
nginx限制并发连接请求数的方法
2021/04/01 Servers