深入理解Node.js 事件循环和回调函数


Posted in Javascript onNovember 02, 2016

本文详细的介绍了Node.js 事件循环和Node.js回调函数,废话不多说了,具体看下面把。

 一、Node.js 事件循环

Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.

1、事件驱动程序

Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。这个模型非常高效可扩展性非常强,因为web server一直接受请求而不等待任何读写操作。(这也被称之为非阻塞式IO或者事件驱动IO)。在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。深入理解Node.js 事件循环和回调函数

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件,如下实例:
  

// 引入 events 模块 
var events = require('events'); 
// 创建 eventEmitter 对象 
var eventEmitter = new events.EventEmitter(); 
以下程序绑定事件处理程序: 
// 绑定事件及事件的处理程序 
eventEmitter.on('eventName', eventHandler); 
我们可以通过程序触发事件: 
// 触发事件 
eventEmitter.emit('eventName');

2、实例

创建 main.js 文件,代码如下所示:

// 引入 events 模块 
var events = require('events'); 
// 创建 eventEmitter 对象 
var eventEmitter = new events.EventEmitter(); 
// 创建事件处理程序 
var connectHandler = function connected() { 
  console.log('连接成功。'); 
  // 触发 data_received 事件 
  eventEmitter.emit('data_received'); 
} 
// 绑定 connection 事件处理程序 
eventEmitter.on('connection', connectHandler); 
// 使用匿名函数绑定 data_received 事件 
eventEmitter.on('data_received', function(){ 
  console.log('数据接收成功。'); 
}); 
// 触发 connection 事件 
eventEmitter.emit('connection'); 
console.log("程序执行完毕。");

深入理解Node.js 事件循环和回调函数

二、Node.js 回调函数

Node.js 异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。

1、阻塞代码实例

创建一个文件 test.txt ,内容如下:

Hello World! 
fs.readFileSync() 
fs.readFile()

创建 test.js 文件, 代码如下:

console.log('-------程序开始执行--------');  
// 引入fs模块 
var fs = require("fs"); 
//同步读取文件 
var data = fs.readFileSync('test.txt','utf-8'); 
console.log(data.toString()); 
console.log('-------程序执行结束--------');

以上代码执行结果如下:深入理解Node.js 事件循环和回调函数

2、非阻塞代码实例

创建 test.js 文件, 代码如下:

console.log('-------程序开始执行--------');  
// 引入fs模块 
var fs = require("fs"); 
//异步读取文件 
fs.readFile('test.txt','utf-8',function (err, data) { 
  if (err) return console.error(err); 
  console.log(data.toString()); 
}); 
console.log('-------程序执行结束--------');

以上程序中 fs.readFile() 是异步函数用于读取文件。如果在读取文件过程中发生错误,错误 err 对象就会输出错误信息。如果没发生错误,readFile 跳过 err 对象的输出,文件内容就通过回调函数输出。

以上代码执行结果如下:深入理解Node.js 事件循环和回调函数
接下来我们删除 input.txt 文件,执行结果如下所示:深入理解Node.js 事件循环和回调函数
 以上两个实例我们了解了阻塞与非阻塞调用的不同。第一个实例在文件读取完后才执行完程序。第二个实例我们不需要等待文件读取完,这样就可以在读取文件时同时执行接下来的代码,大大提高了程序的性能。因此,阻塞按是按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数,我们就需要写在回调函数内。

三、fs.readFileSync和fs.readFile

1、s.readFileSync

语法:fs.readFileSync(filename, [encoding]) 

接收参数:

  filename:文件路径

  options:option对象,包含 encoding,编码格式,该项是可选的。

 由于Node.js仅支持如下编码:utf8, ucs2, ascii, binary, base64, hex,并不支持中文GBK或GB2312之类的编码,因此如果要读写GBK或GB2312格式的文件的中文内容,必须要用额外的模块:iconv-lite。

2、fs.readFile

语法:fs.readFile(filename, [encoding], [callback(err,data)])

接收参数:

  filename:文件路径

  options :option对象,包含 encoding,编码格式,该项是可选的。

  callback :回调,传递2个参数 异常err 和 文件内容 data

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery从头学起第二讲
Jul 04 Javascript
js判断是否为数组的函数: isArray()
Oct 30 Javascript
form.submit()不能提交表单的错误原因及解决方法
Oct 13 Javascript
JavaScript动态改变表格单元格内容的方法
Mar 30 Javascript
基于jQuery实现的扇形定时器附源码下载
Oct 20 Javascript
Vue.js报错Failed to resolve filter问题的解决方法
May 25 Javascript
jquery通过name属性取值的简单实现方法
Jun 20 Javascript
js绘制购物车抛物线动画
Nov 18 Javascript
vue服务端渲染页面缓存和组件缓存的实例详解
Sep 18 Javascript
移动端自适应flexible.js的使用方法(不用三大框架,仅写一个单html页面使用)推荐
Apr 02 Javascript
js实现弹出框的拖拽效果实例代码详解
Apr 16 Javascript
vue@cli3项目模板怎么使用public目录下的静态文件
Jul 07 Javascript
JavaScript 数组的深度复制解析
Nov 02 #Javascript
AngularJS实现与Java Web服务器交互操作示例【附demo源码下载】
Nov 02 #Javascript
Centos7 中 Node.js安装简单方法
Nov 02 #Javascript
AngularJS入门教程之与服务器(Ajax)交互操作示例【附完整demo源码下载】
Nov 02 #Javascript
用AngularJS来实现监察表单按钮的禁用效果
Nov 02 #Javascript
AngularJS入门教程之Cookies读写操作示例
Nov 02 #Javascript
js导出excel文件的简洁方法(推荐)
Nov 02 #Javascript
You might like
PHP及Zend Engine的线程安全模型分析
2011/11/10 PHP
PHP计算数组中值的和与乘积的方法(array_sum与array_product函数)
2016/04/01 PHP
一个tab标签切换效果代码
2009/03/27 Javascript
jQuery EasyUI API 中文文档 - Calendar日历使用
2011/10/19 Javascript
Extjs4 GridPanel的主要配置参数详细介绍
2013/04/18 Javascript
Javascript事件实例详解
2013/11/06 Javascript
javascript将url中的参数加密解密代码
2014/11/17 Javascript
JavaScript判断一个字符串是否包含指定子字符串的方法
2015/03/18 Javascript
JQuery中Text方法用法实例分析
2015/05/18 Javascript
JSON字符串转换JSONObject和JSONArray的方法
2016/06/03 Javascript
js时间戳格式化成日期格式的多种方法介绍
2017/02/16 Javascript
jQuery.Ajax()的data参数类型详解
2017/07/23 jQuery
Node.JS段点续传:Nginx配置文件分段下载功能的实现方法
2018/03/12 Javascript
iview在vue-cli3如何按需加载的方法
2018/10/31 Javascript
js删除数组中某几项的方法总结
2019/01/16 Javascript
使用preload预加载页面资源时注意事项
2020/02/03 Javascript
JavaScript隐式类型转换代码实例
2020/05/29 Javascript
uniapp与webview之间的相互传值的实现
2020/06/29 Javascript
[01:39:04]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第二场 2月1日
2021/03/11 DOTA
[22:07]DOTA2-DPC中国联赛 正赛 iG vs Magma 选手采访
2021/03/11 DOTA
Python 解析pymysql模块操作数据库的方法
2020/02/18 Python
Python多线程threading创建及使用方法解析
2020/06/17 Python
python数据抓取3种方法总结
2021/02/07 Python
HTML5样式控制示例代码
2013/11/27 HTML / CSS
html2canvas生成清晰的图片实现打印的示例代码
2019/09/30 HTML / CSS
Booking.com西班牙:全球酒店预订
2018/03/30 全球购物
女士鞋子、包包和服装在线,第一款10美元:ShoeDazzle
2019/07/26 全球购物
阿联酋手表和配饰购物网站:Rivolishop
2019/11/25 全球购物
毕业生的自我鉴定
2013/10/29 职场文书
老干部工作先进事迹
2014/08/17 职场文书
小学生竞选班干部演讲稿(5篇)
2014/09/12 职场文书
2019年员工晋升管理制度范本!
2019/07/08 职场文书
Nginx + consul + upsync 完成动态负载均衡的方法详解
2021/03/31 Servers
go语言基础 seek光标位置os包的使用
2021/05/09 Golang
Linux中各个目录的作用与内容
2022/06/28 Servers
windows server2016安装oracle 11g的图文教程
2022/07/15 Servers