美文网首页
NodeJS 之 EventEmitter

NodeJS 之 EventEmitter

作者: kviccn | 来源:发表于2016-12-09 23:34 被阅读227次

前言

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

如下图示:


event_loop

详细描述请大家移步这里

背景

我们将通过一颗小树苗的养成记来学习一下EventEmitter中一些有趣的东西。

好了,不说了。撸代码。

// 引入 events 模块
const events = require('events')

// 创建 EventEmitter 实例对象
const 小树苗 = new events.EventEmitter()

/**
 * 我们的思路是这样的
 * 我们现在有一颗小树苗的种子
 * 我们把它种到土里
 * 然后给它浇水
 * 然后给它施肥
 * 然后再给它晒晒太阳
 * 然后...
 * 我们就假装它长大了^_^
 */

/**
 * 我们先写一些事件捕获器
 *(好吧,叫监听器也好)
 * 就好像抓小精灵
 * 抓到了,它总该叫一声吧
 */ 

const 种树捕获器 = () => {
  // 在小种子被种到土里一秒钟后, 土地里发出了一声惨绝人寰的尖叫
  setTimeout(() => {
    console.log('啊,好黑。宝宝被种到土里了')
  }, 1000)
}

const 浇水捕获器 = () => {
  setTimeout(() => {
    console.log('咦, 有好心人给宝宝浇水了')
  }, 2500)
  setTimeout(() => {
    console.log('宝宝发芽了^_^')
  }, 4000)
}

const 施肥捕获器 = () => {
  setTimeout(() => {
    console.log('啊啊啊,好臭啊')
  }, 5500)
  setTimeout(() => {
    console.log('不过宝宝还是长高高了^_^')
  }, 7000)
}

const 晒太阳捕获器 = () => {
  setTimeout(() => {
    console.log('今天阳光好好, 宝宝好开心^_^')
  }, 8500)
}

const 长大了捕获器 = () => {
  setTimeout(() => {
    console.log('嗯。现在, 宝宝已经长大了。')
  }, 10000)
  setTimeout(() => {
    console.log('全剧终')
  }, 12000)
}

// 现在,我们把这些事件和小树苗的成长过程关联起来

小树苗.once('播种', 种树捕获器)
小树苗.on('浇水', 浇水捕获器)
小树苗.on('施肥', 施肥捕获器)
小树苗.on('晒太阳', 晒太阳捕获器)
小树苗.on('长大了', 长大了捕获器)

// 好了,让我们开始种树吧^_^

小树苗.emit('播种')
小树苗.emit('浇水')
小树苗.emit('施肥')
小树苗.emit('晒太阳')
小树苗.emit('长大了')

动图看效果:

解释

  1. 首先,我们写了一些事件监听器(EventListener)
  2. 然后,我们把事件监听器和相应的事件关联了起来,即为指定事件注册一个监听器
  3. 最后,我们触发了这些事件

用到的方法

once(event, listener)
为指定事件注册一个单次监听器,即监听器最多只会触发一次,触发后立刻解除该监听器

on(event, listener)
为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数

emit(event, [arg1], [arg2], [...])
按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false

没有用到的方法

addListener(event, listener)
为指定事件添加一个监听器到监听器数组的尾部

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

removeAllListeners([event])
移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器

setMaxListeners(n)
默认情况下, EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息
setMaxListeners 函数用于提高监听器的默认限制的数量

listeners(event)
返回指定事件的监听器数组

上代码:

const events = require('events')
const EventEmitter = events.EventEmitter

const demo = new EventEmitter()

const listener1 = () => {
  console.log('connected to listener1')
}

const listener2 = () => {
  console.log('connected to listener2')
}

demo.addListener('connection', listener1)
demo.addListener('connection', listener2)

// listenerCount(emitter, event) 返回指定事件的监听器数量
let CountOfListener = EventEmitter.listenerCount(demo, 'connection')
console.log(`监听器个数: ${CountOfListener}`)

demo.emit('connection')

demo.removeListener('connection', listener1)
console.log('移除listener1')

demo.emit('connection')

CountOfListener = EventEmitter.listenerCount(demo, 'connection')
console.log(`监听器个数: ${CountOfListener}`)

// 举个emit传递参数的栗子
demo.addListener('go', (who , source, dest) => {
  console.log(`${who}从${source}到${dest}去`)
})
demo.emit('go', '小明', '地上', '天上')

console.log('complete')

运行结果如下:

写在最后

这这这这还能用汉语直接撸代码?!!


没错,JS就是这么神奇。

感谢看到这篇文章的你。
好了,睡觉。_

相关文章

网友评论

      本文标题:NodeJS 之 EventEmitter

      本文链接:https://www.haomeiwen.com/subject/wzlymttx.html