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 程序库的比较(一)之DOM功能
Apr 07 Javascript
用jQuery获取IE9下拉框默认值问题探讨
Jul 22 Javascript
js实现动态改变字体大小代码
Jan 02 Javascript
瀑布流布局代码一例
Apr 11 Javascript
JavaScript中判断数据类型的方法总结
May 24 Javascript
Radio 单选JS动态添加的选项onchange事件无效的解决方法
Dec 12 Javascript
js中DOM三级列表(代码分享)
Mar 20 Javascript
Bootstrap table学习笔记(2) 前后端分页模糊查询
May 18 Javascript
Express下采用bcryptjs进行密码加密的方法
Feb 07 Javascript
ios中视频的最后一桢问题解决
May 14 Javascript
基于 vue-skeleton-webpack-plugin 的骨架屏实战
Aug 05 Javascript
解决vue cli使用typescript后打包巨慢的问题
Sep 30 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/08/08 PHP
PHP读取txt文件的内容并赋值给数组的代码
2011/11/03 PHP
PHP制作百度词典查词采集器
2015/01/29 PHP
如何使用PHP Embed SAPI实现Opcodes查看器
2015/11/10 PHP
php读取sqlite数据库入门实例代码
2014/06/25 Javascript
JavaScript实现生成GUID(全局统一标识符)
2014/09/05 Javascript
javascript中slice(),splice(),split(),substring(),substr()使用方法
2015/03/13 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
2015/11/23 Javascript
js判断上传文件后缀名是否合法
2016/01/28 Javascript
微信小程序 二维码canvas绘制实例详解
2017/01/06 Javascript
基于JavaScript实现移动端无限加载分页
2017/03/27 Javascript
详解微信小程序设置底部导航栏目方法
2017/06/29 Javascript
Vue.js做select下拉列表的实例(ul-li标签仿select标签)
2018/03/02 Javascript
vue的全局变量和全局拦截请求器的示例代码
2018/09/13 Javascript
Vue-Router基础学习笔记(小结)
2018/10/15 Javascript
vue-cli3 项目优化之通过 node 自动生成组件模板 generate View、Component
2019/04/30 Javascript
haskell实现多线程服务器实例代码
2013/11/26 Python
python模块简介之有序字典(OrderedDict)
2016/12/01 Python
Python3.5基础之函数的定义与使用实例详解【参数、作用域、递归、重载等】
2019/04/26 Python
Python使用sys.exc_info()方法获取异常信息
2020/07/23 Python
详解HTML5如何使用可选样式表为网站或应用添加黑暗模式
2020/04/07 HTML / CSS
优质美利奴羊毛袜,不只是徒步旅行:Darn Tough Vermont
2018/11/05 全球购物
ghd法国官方网站:英国最受欢迎的美发工具品牌
2019/04/18 全球购物
巴西24小时在线药房:Drogasil
2020/06/20 全球购物
SQL中where和having的区别
2012/06/17 面试题
数学专业毕业生自荐信
2013/11/10 职场文书
社会治安综合治理管理责任书
2014/04/16 职场文书
煤矿安全演讲稿
2014/05/09 职场文书
中华在我心中演讲稿
2014/09/13 职场文书
2014年社区党建工作汇报材料
2014/11/02 职场文书
求职自我评价怎么写
2015/03/09 职场文书
仙境之桥观后感
2015/06/16 职场文书
2019西餐厅创业计划书范文!
2019/07/12 职场文书
php 获取音视频时长,PHP 利用getid3 获取音频文件时长等数据
2021/04/01 PHP
golang fmt格式“占位符”的实例用法详解
2021/07/04 Golang
python基础之类方法和静态方法
2021/10/24 Python