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 覆盖和重载 函数
Sep 25 Javascript
动态加载js和css(外部文件)
Apr 17 Javascript
Google 地图类型详解及示例代码
Aug 06 Javascript
JS中this上下文对象使用方式
Oct 09 Javascript
原生js编写基于面向对象的分页组件
Dec 05 Javascript
js实现定时进度条完成后切换图片
Jan 04 Javascript
非常实用的vue导航钩子
Mar 20 Javascript
基于JavaScript实现的希尔排序算法分析
Apr 14 Javascript
react-router中的属性详解
Jun 01 Javascript
解决jquery appaend元素中id绑定事件失效的问题
Sep 12 jQuery
关于layui的动态图标不显示的解决方法
Sep 04 Javascript
前端开发基础javaScript的六大作用
Aug 06 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制作的意见反馈表源码
2007/03/11 PHP
PHP采集腾讯微博的实现代码
2012/01/19 PHP
php5.x禁用eval的操作方法
2018/10/19 PHP
php多进程中的阻塞与非阻塞操作实例分析
2020/03/04 PHP
javascript中定义私有方法说明(private method)
2014/01/27 Javascript
Node.js实现在目录中查找某个字符串及所在文件
2014/09/03 Javascript
javascript 动态修改css样式方法汇总(四种方法)
2015/08/27 Javascript
jQuery 更改checkbox的状态,无效的解决方法
2016/07/22 Javascript
Vue.js第二天学习笔记(vue-router)
2016/12/01 Javascript
Javascript基础回顾之(二) js作用域
2017/01/31 Javascript
JavaScript运动框架 多值运动(四)
2017/05/18 Javascript
Angular2学习教程之组件中的DOM操作详解
2017/05/28 Javascript
ReactJs设置css样式的方法
2017/06/08 Javascript
Webpack 之 babel-loader文件预处理器详解
2018/03/23 Javascript
LayUi中接口传数据成功,表格不显示数据的解决方法
2018/08/19 Javascript
jQuery实现的简单手风琴效果示例
2018/08/29 jQuery
CryptoJS中AES实现前后端通用加解密技术
2018/12/18 Javascript
JS隐藏号码中间4位代码实例
2019/04/09 Javascript
利用Vue-draggable组件实现Vue项目中表格内容的拖拽排序
2019/06/07 Javascript
H5+css3+js搭建带验证码的登录页面
2020/10/11 Javascript
Python实现生成简单的Makefile文件代码示例
2015/03/10 Python
Python实现求数列和的方法示例
2018/01/12 Python
python3结合openpyxl库实现excel操作的实例代码
2018/09/11 Python
Python 开发工具PyCharm安装教程图文详解(新手必看)
2020/02/28 Python
Django haystack实现全文搜索代码示例
2020/11/28 Python
Ubuntu16安装Python3.9的实现步骤
2020/12/15 Python
Annoushka英国官网:英国奢侈珠宝品牌
2018/10/20 全球购物
求职信的最佳写作思路
2014/02/01 职场文书
《学会合作》教学反思
2014/04/12 职场文书
三严三实对照检查材料范文
2014/09/23 职场文书
2015年妇产科工作总结
2015/05/18 职场文书
创业计划书之酒吧
2019/12/02 职场文书
Python 多线程之threading 模块的使用
2021/04/14 Python
python 如何在list中找Topk的数值和索引
2021/05/20 Python
Win11 PC上的Outlook搜索错误怎么办?
2022/07/15 数码科技