NodeJS 之 EventEmitter

前言

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就是这么神奇。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • https://nodejs.org/api/documentation.html 工具模块 Assert 测试 ...
    KeKeMars阅读 6,221评论 0 6
  • 本文包括:1、Listener简介2、Servlet监听器3、监听三个域对象创建和销毁的事件监听器4、监听三个域对...
    廖少少阅读 5,893评论 6 28
  • 毫无疑问,nodeJS改变了整个前端开发生态。本文通过分析nodeJS当中events模块源码,由浅入深,动手实现...
    LucasHC阅读 1,836评论 3 17
  • 蒙蒙细雨,轻舟载人,青石小巷,恰好相遇。撑伞的我,躲雨的你。无意一撇,缘结于此。风雨同舟,君子之交。木青幕府。我在...
    千诡阅读 207评论 0 0