终极目标:掌握和使用node

本博客目的:记录node学习的进度和心得

内容:Nodejs中的Nodejs的非阻塞I/O、异步、事件驱动。

Nodejs的单线程、非阻塞I/O、事件驱动

​ 在Java、PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。要让Web应用程序支持更多的用户,就需要增加服务器的数量,而Web应用程序的硬件成本当然就上升了。 (高并发场景)

​ Node.js不为每个客户连接创建一个新的线程,而仅仅使用一个线程。当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。使用Node.js,一个8GB内存的服务器,可以同时处理超过4万用户的连接。

​ 之前,我们使用fs模块的readFile方法是一个异步方法,或者说是非阻塞式IO。

​ 所以代码:

image-20200514162310289

​ 结果:

image-20200514162319039

但是,当我们在外部使用这个异步方法的时候,会出undefined

image-20200514162610600

因为,这个方法是异步的,最后才会返回第3步,data没有在getMime方法结束前返回。

所以,通常的方法是回调函数的方法解决这种异步问题。

Nodejs回调处理异步

image-20200514162911561

相当于callback在异步方法中留了一个钩子,等待异步处理完成,传入data给callback,自然也获取了到这个data。

此外,我们可以使用events模块。

Nodejs events模块处理异步

​ Node.js 事件循环: Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。

Node.js每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。

​ Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件(广播与接收广播,即事件驱动)。

​ 首先,查看一下events模块

image-20200514163306943

image-20200514163315029

​ 有很多属性。

​ 通常,我们通过实例化 EventEmitter 类来绑定和监听事件,即广播事件,接收广播,出发事件的相关操作方法。

​ 例如:

image-20200514164135200

image-20200514164145399

注意的是,EventEmitter.emit('to_parent','发送的数据')中发射to_parent事件并且是把 发送的数据 作为数据传送出去的,这是可以被监听到的。(这类似于vue中的子组件与父组件通信(子传父的情况)。)

类似地,事件的广播和监听可以循环嵌套(事件驱动):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 引入 events 模块

var events=require('events');

//console.log(events);

var EventEmitter=new events.EventEmitter();//实例化ventEmitter

//广播 和接收广播(事件驱动)

EventEmitter.on('to_mime',function(data){

console.log(data);

})

//监听to_parent的广播
EventEmitter.on('to_parent',function(data){
//console.log('接收到了这个广播事件');

console.log(data);

EventEmitter.emit('to_mime','给mime发送的数据')

})

setTimeout(function(){
console.log('开始广播...');
//广播to_parent事件
EventEmitter.emit('to_parent','发送的数据')

},1000);

image-20200514164718390

nodejs事件驱动获取数据

所以我们用事件驱动的方法,接收fs异步处理的数据。

image-20200514165159839

拿到了对应的数据

image-20200514165217037

处理fs异步读取的问题

在上一个blog中,fs的readFile是一个异步读取的方法,我们不能正确读取文件,所以采用了fs.readFileSync同步读取。

这里,我们可以使用刚刚讲的两种处理异步的方式解决这个问题。

1、使用回调函数的方式

image-20200514165629455

2、使用event模块的发射事件与监听事件

image-20200514165656301

注意:对应调用的格式和参数要相应修改。