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 对象定义方法 简单易学
Mar 22 Javascript
jQuery toggleClass应用实例(附效果图)
Apr 06 Javascript
jQuery替换textarea中换行的方法
Jun 10 Javascript
JQuery删除DOM节点的方法
Jun 11 Javascript
浅谈Jquery核心函数
Jun 18 Javascript
jQuery 3.0中存在问题及解决办法
Jul 15 Javascript
基于jquery实现弹幕效果
Sep 29 Javascript
jQuery实现单击按钮遮罩弹出对话框效果(2)
Feb 20 Javascript
JavaScript输入框字数实时统计更新
Jun 17 Javascript
vue-cli 打包后提交到线上出现 &quot;Uncaught SyntaxError:Unexpected token&quot; 报错
Nov 06 Javascript
解决Layui当中的导航条动态添加后渲染失败的问题
Sep 25 Javascript
用Angular实现一个扫雷的游戏示例
May 15 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
业余方法DIY电子管FM收音机
2021/03/02 无线电
解析thinkphp中的M()与D()方法的区别
2013/06/22 PHP
关于php微信订阅号开发之token验证后自动发送消息给订阅号但是没有消息返回的问题
2015/12/21 PHP
Nigma vs AM BO3 第二场2.13
2021/03/10 DOTA
基于jQuery实现点击同时更改两个iframe的网址
2010/07/01 Javascript
解决3.01版的jquery.form.js中文乱码问题的解决方法
2012/03/08 Javascript
js获得当前系统日期时间的方法
2015/05/06 Javascript
JavaScript中解析JSON数据的三种方法
2015/07/03 Javascript
js实现汉字排序的方法
2015/07/23 Javascript
仅30行代码实现Javascript中的MVC
2016/02/15 Javascript
jQuery对象的链式操作用法分析
2016/05/10 Javascript
VUEJS实战之利用laypage插件实现分页(3)
2016/06/13 Javascript
Node.js读写文件之批量替换图片的实现方法
2016/09/07 Javascript
AJAX和jQuery动态加载数据的实现方法
2016/12/05 Javascript
jQuery回调方法使用示例
2017/06/26 jQuery
在Vue中使用echarts的方法
2018/02/05 Javascript
一次Webpack配置文件的分离实战记录
2018/11/30 Javascript
vue基础之事件简写、事件对象、冒泡、默认行为、键盘事件实例分析
2019/03/11 Javascript
在React中写一个Animation组件为组件进入和离开加上动画/过度效果
2019/06/24 Javascript
JavaScript实现轮播图效果代码实例
2019/09/28 Javascript
js生成1到100的随机数最简单的实现方法
2020/02/07 Javascript
Python Dataframe 指定多列去重、求差集的方法
2018/07/10 Python
pandas 把数据写入txt文件每行固定写入一定数量的值方法
2018/12/28 Python
Django如何实现上传图片功能
2019/08/16 Python
Python常用数据类型之间的转换总结
2019/09/06 Python
Python依赖包迁移到断网环境操作
2020/07/13 Python
Python CategoricalDtype自定义排序实现原理解析
2020/09/11 Python
HTML5 manifest离线缓存的示例代码
2018/08/08 HTML / CSS
Html5原生拖拽相关事件简介以及基础实现
2020/11/19 HTML / CSS
蔻驰美国官网:COACH美国
2016/08/18 全球购物
New Balance加拿大官方网站:运动鞋和健身服装
2018/11/19 全球购物
介绍一下Cookie和Session及他们之间的区别
2012/11/20 面试题
挂牌仪式主持词
2014/03/20 职场文书
法制报告会主持词
2014/04/02 职场文书
学校爱国卫生月活动总结
2014/06/25 职场文书
党委班子剖析材料
2014/08/21 职场文书