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 相关文章推荐
Prototype 学习 工具函数学习($w,$F方法)
Jul 12 Javascript
jQuery1.6 使用方法二
Nov 23 Javascript
Jquery和JS用外部变量获取Ajax返回的参数值的方法实例(超简单)
Jun 17 Javascript
Javascript函数式编程简单介绍
Oct 11 Javascript
详解AngularJS中的filter过滤器用法
Jan 04 Javascript
Bootstrap进度条组件知识详解
May 01 Javascript
JS制作类似选项卡切换的年历
Dec 03 Javascript
JS实现touch 点击滑动轮播实例代码
Jan 19 Javascript
JavaScript函数的4种调用方法实例分析
Mar 05 Javascript
json字符串对象转换代码实例
Sep 28 Javascript
浅谈vuex为什么不建议在action中修改state
Feb 02 Javascript
jQuery实现简易QQ聊天框
Feb 10 jQuery
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
DC的38部超级英雄动画电影
2020/03/03 欧美动漫
zend framework重定向方法小结
2016/05/28 PHP
golang 调用 php7详解及实例
2017/01/04 PHP
PHP实现将多个文件压缩成zip格式并下载到本地的方法示例
2018/05/23 PHP
YII框架学习笔记之命名空间、操作响应与视图操作示例
2019/04/30 PHP
使用JS操作页面表格,元素的一些技巧
2007/02/02 Javascript
文本框获得焦点和失去焦点的判断代码
2012/03/18 Javascript
JavaScript学习笔记记录我的旅程
2012/05/23 Javascript
基于jquery的滚动条滚动固定div(附演示下载)
2012/10/29 Javascript
Js 冒泡事件阻止实现代码
2013/01/27 Javascript
javascript拖拽应用实例
2016/03/25 Javascript
jquery模拟多级复选框效果的简单实例
2016/06/08 Javascript
基于JavaScript实现拖动滑块效果
2017/02/16 Javascript
Web开发中客户端的跳转与服务器端的跳转的区别
2017/03/05 Javascript
jquery.flot.js简单绘制折线图用法示例
2017/03/13 Javascript
jquery 校验中国身份证号码实例详解
2017/04/11 jQuery
利用JS hash制作单页Web应用的方法详解
2017/10/10 Javascript
JavaScript new对象的四个过程实例浅析
2018/07/31 Javascript
vue操作下拉选择器获取选择的数据的id方法
2018/08/24 Javascript
解决vue初始化项目时,一直卡在Project description上的问题
2019/10/31 Javascript
JS 数组和对象的深拷贝操作示例
2020/06/06 Javascript
微信小程序连续签到7天积分获得功能的示例代码
2020/08/20 Javascript
python数据库操作常用功能使用详解(创建表/插入数据/获取数据)
2013/12/06 Python
Django自定义用户认证示例详解
2018/03/14 Python
python的中异常处理机制
2018/08/30 Python
Python3.5内置模块之shelve模块、xml模块、configparser模块、hashlib、hmac模块用法分析
2019/04/27 Python
Django处理多用户类型的方法介绍
2019/05/18 Python
在Pytorch中计算自己模型的FLOPs方式
2019/12/30 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
2020/02/17 Python
Python 实现将大图切片成小图,将小图组合成大图的例子
2020/03/14 Python
Mytheresa英国官网:拥有160多个奢侈品品牌
2016/10/09 全球购物
美国CVS药店官网:CVS Pharmacy
2018/07/26 全球购物
Farfetch巴西官网:奢侈品牌时尚购物平台
2020/10/19 全球购物
金鑫耀Java笔试题
2014/09/06 面试题
学生出入校管理制度
2014/01/16 职场文书
HTML+JS实现在线朗读器
2022/02/15 Javascript