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 相关文章推荐
js下写一个事件队列操作函数
Jul 19 Javascript
Javascript中的String对象详谈
Mar 03 Javascript
CSS3实现动态背景登录框的代码
Jul 28 Javascript
jQuery+PHP实现可编辑表格字段内容并实时保存
Oct 09 Javascript
详解js跨域原理以及2种解决方案
Dec 09 Javascript
Vue.js基础知识汇总
Apr 27 Javascript
手机浏览器 后退按钮强制刷新页面方法总结
Oct 09 Javascript
javascript中的隐式调用
Feb 10 Javascript
基于Vue实现关键词实时搜索高亮显示关键词
Jul 21 Javascript
js实现ATM机存取款功能
Oct 27 Javascript
详解Node.js一行命令上传本地文件到服务器
Apr 22 Javascript
详解如何在vue项目中使用layui框架及采坑
May 05 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
一个用于网络的工具函数库
2006/10/09 PHP
php下用GD生成生成缩略图的两个选择和区别
2007/04/17 PHP
我整理的PHP 7.0主要新特性
2016/01/07 PHP
PHP 数组基本操作小结(推荐)
2016/06/13 PHP
php使用PDO执行SQL语句的方法分析
2017/02/16 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
基于jQuery的Spin Button自定义文本框数值自增或自减
2010/07/17 Javascript
jQuery示例收集
2010/11/05 Javascript
原生JS可拖动弹窗效果实例代码
2013/11/09 Javascript
innerHTML,outerHTML,innerText,outerText的用法及区别解析
2013/12/16 Javascript
jquery实现的鼠标下拉滚动置顶效果
2014/07/24 Javascript
JQuery插件jcarousellite的参数中文说明
2015/05/11 Javascript
大型JavaScript应用程序架构设计模式
2016/06/29 Javascript
jquery轮播的实现方式 附完整实例
2016/07/28 Javascript
详细谈谈AngularJS的子级作用域问题
2016/09/05 Javascript
JavaScript实现经纬度转换成地址功能
2017/03/28 Javascript
详解webpack 配合babel 将es6转成es5 超简单实例
2017/05/02 Javascript
Vue.js 事件修饰符的使用教程
2018/11/01 Javascript
JS div匀速移动动画与变速移动动画代码实例
2019/03/26 Javascript
node实现socket链接与GPRS进行通信的方法
2019/05/20 Javascript
对python制作自己的数据集实例讲解
2018/12/12 Python
在Python中,不用while和for循环遍历列表的实例
2019/02/20 Python
PyTorch搭建多项式回归模型(三)
2019/05/22 Python
selenium+python自动化测试环境搭建步骤
2019/06/03 Python
Python2 与Python3的版本区别实例分析
2020/03/30 Python
使用scrapy ImagesPipeline爬取图片资源的示例代码
2020/09/28 Python
英国领先的鞋类零售商和顶级品牌的官方零售商:Wynsors
2020/02/17 全球购物
新闻专业应届生求职信
2013/10/31 职场文书
医学专业本科毕业生自我鉴定
2013/12/28 职场文书
小学生竞选班长演讲稿
2014/04/24 职场文书
道德演讲稿
2014/05/21 职场文书
警察群众路线对照检查材料思想汇报
2014/10/01 职场文书
2015年学校图书室工作总结
2015/05/19 职场文书
会计工作自我鉴定范文
2019/06/21 职场文书
mysql多表查询-笔记七
2021/04/05 MySQL
德劲DE1107指针试高灵敏度全波段收音机机评
2022/04/05 无线电