node设计模式 - 简介

Reactor模式简介

Reactor模式结构图:
在这里插入图片描述

使用Reactor模式时发生的操作:

首先应用程序接收到I/O请求时,会将其提交至Event Demultiplexer(事件多路分解器),让其生成新的I/O操作。应用程序还会为新的I/O请求指定一个处理程序,当操作完成时将调用该处理程序。当向Event Demultiplexer提交新请求后,Event Demultiplexer会立即将控制权返回给应用程序。当一组I/O操作完成时,事件多路分解器将该I/O操作对应的事件推入Event Queue(事件队列),此时Event Loop开始遍历其中的项目,对于每个项目调用其对应的处理程序,由于每个I/O的处理程序是应用程序的一部分,故此时将控制权交给应用程序,由其去执行处理程序,当处理完后再将控制权交还给Event LoopEvent Loop再去调用下一个项目对应的处理程序。在处理程序执行过程中可能会请求新的异步操作,从而会导致新的操作被插入到Event Demultiplexer。当Event Loop中的所有项目被处理完时,循环将再次阻塞Event Demultiplexer,当有新事件可用时,Event Demultiplexer将触发另一个周期。

异步行为: 应用程序会在一个时间点(不阻塞)访问资源,并为该操作提供一个处理程序,当操作完成时,处理程序将在另一个时间点被调用该操作相关的处理程序。

Node.js的核心定义模式:

模式(reactor)通过阻塞来处理I/O,直到一组被观察资源的新事件可用,然后将每个事件分派到相关联的处理程序来做出反应。

回调模式

回调是Reactor模式处理程序的实现。回调是被调用来传播操作结果的函数,这正是我们在处理异步操作时所需要的。它们会替代总是同步执行的return指令。

CPS

js中,回调是一个作为参数传递给另一个函数的函数,当操作完成时将调用该结果。在函数编程中,这种传播结果的方式称为CPS。这是一个通用的概念,它并不总是与异步操作相关联。事实上,它只是表示通过将结果传递给另一个函数(回调)而使结果传播,而不是直接返回给调用者。

同步CPS
function add (a, b, callback) {
         callback(a+b)
 }
 
 console.log('before')
add(1, 2, (result) => {
     console.log(result)
})
 console.log('after')

输出结果:
在这里插入图片描述

异步CPS
function addtionAsync (a, b, callback) {
    setTimeout(() => callback(a + b), 100)
}
console.log('before')
addtionAsync(1, 2, result => console.log('Result: ' +result))
console.log('after')

输出结果:
在这里插入图片描述

由于setTimeout()触发异步操作,它不会等待要执行的回调,而是立即返回,将控制权返回给addtionAsync(),然后再把控制权返回给调用者。在Node.js中该特性非常重要,因为它会在发送异步请求后立即将控制权返回给事件循环,以处理来自队列的新事件

工作原理

在这里插入图片描述

EventEmitter

  1. events模块只提供一个对象:events.EventEmitter(调用events.EventEmitter()方法可以获取EventEmitter类)。EventEmitter的核心就是事件触发与事件监听器功能的封装
  2. EventEmitter对象如果在实例化时发生错误,会触发error事件
  3. 对于同步事件,需要先注册后发送(即on方法在emit之前执行)。对于异步事件,由于事件是异步发出的,即便是看起来emiton之前调用(实际上不是的,只是位置在on前,执行仍在on后),但实际上也是先注册后发送。
1. 使用步骤:
  1. 引入events模块:let events = require('events')
  2. 创建EventEmitter对象:let eventEmitter = new events.EventEmitter()
  3. 使用(注册事件、给事件绑定监听器、移除事件的监听器…)
2. EventEmitter对象方法
eventEmitter.on(事件名称,监听器(函数))
  1. 为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
  2. 当向eventEmitter对象发送事件时(调用emit方法绑定事件名称名称),会调用该事件的监听器(函数)
eventEmitter.emit(事件名称, [args1], [args2], [...])
  1. 按照注册顺序执行执行每个监听器
  2. 如果事件有注册监听返回 true,否则返回 false。
  3. args参数代表了给监听器传入的参数
eventEmitter.addListener(事件名称,监听器(函数))

为指定事件添加一个监听器到监听器数组的尾部(即最后执行)

eventEmitter.once(事件名称,监听器(函数))

为指定事件注册一个单次监听器(该监听器只触发一次,触发完后移除)

eventEmitter.removeListener(事件名称,监听器名称(函数名称))

移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器

eventEmitter.removeAllListeners([事件名称])

移除所有事件的所有监听器(即没有参数);如果指定事件(即给定参数),则移除指定事件的所有监听器

eventEmitter.listeners(事件名称)

返回指定事件的监听数组(返回的是函数集合,可取每一个元素进行调用执行

3. EventEmitter类方法
events.emitter.listenerCount(eventName)

获取指定事件的监听器个数

4. 事件

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43314846/article/details/107243816
今日推荐