位置: 编程技术 - 正文

Node.js中使用事件发射器模式实现事件绑定详解(nodejs示例)

编辑:rootadmin

推荐整理分享Node.js中使用事件发射器模式实现事件绑定详解(nodejs示例),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:nodejs怎么使用,node.js in action,node.js用途,node.js使用教程,node.js使用教程,node.js的使用,node.js用途,node.js用途,内容如对您有帮助,希望把文章链接给更多的朋友!

在Node里,很多对象都会发射事件。比如,一个TCP服务器,每当有客户端请求连接就会发射“connect”事件,又比如,每当读取一整块数据,文件系统就会发射一个“data”事件。这些对象在Node里被称为事件发射器(event emitter)。事件发射器允许程序员订阅他们感兴趣的事件,并将回调函数绑定到相关的事件上,这样每当事件发射器发射事件时回调函数就会被调用。发布/订阅模式非常类似传统的GUI模式,比如按钮被点击时程序就会收到相应的通知。使用这种模式,服务端程序可以在一些事件发生时作出反应,比如有客户端连接,socket上有可用数据,或者文件被关闭的时候。

还可以创建自己的事件发射器,事实上,Node专门提供了一个EventEmitter伪类,可以把它当作基类来创建自己的事件发射器。

理解回调模式

异步编程不使用函数返回值来表明函数调用的结束,而是采用后继传递风格。

“后继传递风格”(CPS:Continuation-passing style)是一种编程风格,流程控制被显式传递给下一步操作……

CPS风格的函数会接受一个函数作为额外参数,这个函数用来显式指出程序控制的下个流程,当CPS函数计算出它的“返回值”,它就会调用那个代表了程序下个流程的函数,并将CPS函数的“返回值”作为其参数。

出自维基百科—— http.request API(见后面章节)创建一个HTTP请求来访问远程HTTP服务器时的两个必要步骤。第一行采用了“后继传递风格”(CPS:Continuation-passing style),传递了一个当HTTP响应时会被调用的内联函数。HTTP请求API在这儿使用CPS是因为程序需要在http.request函数执行完毕后才继续执行后续操作。

当http.request执行完毕,就会调用那个匿名回调函数,然后将HTTP响应对象作为参数传递给它,这个HTTP响应对象是个事件发射器,根据Node文档,它可以发射包括data,end在内的很多事件,你注册的那些回调函数会在每次事件发生时被调用。

作为一条经验,当你需要在请求的操作完成后重新获取执行权时使用CPS模式,以及当事件可以发生多次时使用事件发射器模式。

理解事件类型

被发射的事件都有一个用字符串表示的类型,前面的例子包含“data”和“end”两个事件类型,它们是由事件发射器来定义的任意字符串,不过约定俗成的是,事件类型通常都由不包含空字符的小写单词组成。

不能用代码来推断出事件发射器能产生哪些类型的事件,因为事件发射器API并没有内省机制,因此你使用的API应该有文档来表明它能发射那些类型的事件。

一旦事件发生,事件发射器就会调用跟事件相关的监听器,并将相关数据作为参数传递给监听器。在前面http.request那个例子里,“data”事件回调函数接受一个data对象作为它第一个也是唯一的参数,而“end”不接受任何数据,这些参数作为API契约的一部分也是由API的作者主观定义的,这些回调函数的参数签名也会在每个事件发射器的API文档里有说明。

事件发射器虽然是个为所有类型事件服务的接口,不过“error”事件是Node里的一个特殊实现。Node里的大多数事件发射器都会在程序发生错误时产生“error”事件,如果程序没有监听某个事件发射器的 “error”事件,事件发射器将会注意到并在错误发生时向上抛出一个未捕获异常。

你可以在Node PERL里运行下面的代码来测试下效果,它模拟了一个能产生两种事件的事件发射器:

你将会看到下面的输出:

代码第2行,随便发射了一个叫“event1”的事件,没有任何效果,但是当发射“error”事件时,错误被抛出到堆栈。如果程序不是运行在PERL命令行环境里,程序将会因为未捕获的异常而崩溃。

使用事件发射器API

任何实现了事件发射器模式的对象(比如TCP Socket,HTTP 请求等)都实现了下面的一组方法:

下面我们具体介绍它们。

使用.addListener()或.on()绑定回调函数

通过指定事件类型和回调函数,你可以注册当事件发生时被执行的操作。比如,文件读取数据流时如果有可用的数据块,就会发射一个“data”事件,下面代码展示如何通过传入一个回调函数来让程序告诉你发生了data事件。

你也可以使用.on,它只是.addListener的简写方式,下面的代码和上面的是一样的:

前面代码,使用事先定义的一个的命名函数作为回调函数,你也可以使用一个内联匿名函数来简化代码:

前面说过,传递给回调函数的参数个数和签名依赖于具体的事件发射器对象和事件类型,它们并不是被标准化的,“data”事件可能传递的是一个数据缓冲对象,“error”事件传递一个错误对象,数据流的“end”事件不向事件监听器传递任何数据。

绑定多个事件监听器

事件发射器模式允许多个事件监听器监听同一个事件发射器的同一事件类型,比如:

事件发射器负责按监听器的注册顺序调用指定事件类型上绑定的所有监听器,也就是说:

1.当事件发生后事件监听器可能不会被立刻调用,也许会有其它事件监听器在它之前被调用。2.异常被抛出到堆栈是不正常的行为,可能是因为代码里有bug,当事件被发射时,如果有一个事件监听器在被调用时抛出了异常,可能会导致一些事件监听器永远不会被调用。这种情况下,事件发射器会捕获到异常,也许还会处理它。

看下面这个例子:

因为第一个监听器抛出了异常,因此第二个监听器不会被调用。

用.removeListener()从事件发射器移除一个事件监听器

Node.js中使用事件发射器模式实现事件绑定详解(nodejs示例)

如果当你不再关心一个对象的某个事件时,你可以通过指定事件类型和回调函数来取消已注册的事件监听器,像这样:

这个例子里,最后一行把一个可能在将来被随时调用的事件监听器从事件发射器对象移除了。

为了删除监听器,你必须给回调函数命名,因为在添加和删除的时候需要回调函数的名字。

使用.once()让回调函数最多执行一次

如果你想监听一个最多执行一次的事件,或者只对某个事件发生的第一次感兴趣,可以用.once()函数:

上面的代码,receiveData函数只会被调用一次。如果readStream对象发射了data事件,receiveData回调函数将会而且仅会被触发一次。

它其实只是个方便方法,因为很简单的就能实现它,像这样:

上面代码里,你重新定了EventEmitter.prototype.once函数,同时也重定义了每个继承自EventEmitter的所有对象的once函数。代码只是简单的使用.on()方法,一旦收到了事件,就用.removeEventListener()取消回调函数的注册,并调用原来的回调函数。

注意:前面代码里使用了function.apply()方法,它接受一个对象并把它作为内含的this变量,以及一个参数数组。前面例子里,通过事件发射器把未修改过的参数数组透明地传递给回调函数。

用.removeAllListeners()从事件发射器移除所有事件监听器

你可以像下面那样从事件发射器移除所有注册到指定事件类型上的所有监听器:

比如,你可以这样取消所有进程中断信号的监听器:

注意:作为一条经验,推荐你只在确切知道删除了什么内容时才使用这个函数,否则,应该让应用程序其它部分来删除事件监听器集合,或者也可以让程序的那些部分自己负责移除监听器。但不管怎样,在某些罕见的场景下,这个函数还是很有用的,比如当你准备有序的关闭一个事件发射器或者关闭整个进程的时候。

创建事件发射器

事件发射器用一个很棒的方式让编程接口变得更通用,在一个常见易懂的编程模式里,客户端直接调用各种函数,而在事件发射器模式中,客户端被绑定到各种事件上,这会让你的程序变得更灵活。(译者注:这句不太自信,贴出原文:The event emitter provides a great way of making a programming interface more generic. When you use a common understood pattern, clients bind to events instead of invoking functions, making your program more flexible.)

此外,通过使用事件发射器,你还可以获得许多特性,比如在同一事件上绑定多个互不相关的监听器。

从Node事件发射器继承

如果你对Node的事件发射器模式感兴趣,并打算用到自己的应用程序里,你可以通过继承EventEmitter来创建一个伪类:

注意:util.inherits建立了MyClass的原形链,让你的MyClass实例可以使用EventEmitter的原形方法。

发射事件

通过继承自EventEmitter,MyClass可以像这样发射事件了:

上面的代码,当someMethond方法被MyClass的实例调用时,就会发射一个叫“cuteom event”的事件,这个事件还会发射两个字符串作为数据:“argument 1”和“argument 2”,它们将会作为参数传递给事件监听器。

MyClass实例的客户端可以像这样监听“custom event”事件:

再比如,你可以这样创建一个每秒发射一次“tick”事件的Ticker类:

用Ticker类的客户端可以展示如何使用Ticker类和监听“tick”事件,

小结

事件发射器模式是种可重入模式(recurrent pattern),可以用它将事件发射器对象从一组特定事件的代码中解耦合。

可以用event_emitter.on()来为特定类型的事件注册监听器,并用event_emitter.removeListener()来取消注册。

还可以通过继承EventEmitter和简单的使用.emit()函数来创建自己的事件发射器。

Node.js模块加载详解 JavaScript是世界上使用频率最高的编程语言之一,它是Web世界的通用语言,被所有浏览器所使用。JavaScript的诞生要追溯到Netscape那个时代,它的核心内容

Node.js中创建和管理外部进程详解 Node被设计用来高效的处理I/O操作,但是你应该知道,有些类型的程序并不适合这种模式。比如,如果你打算用Node处理一个CPU密集的任务,你可能会堵塞

Node.js中使用Buffer编码、解码二进制数据详解 JavaScript很擅长处理字符串,但是因为它最初的设计是用来处理HTML文档,因此它并不太擅长处理二进制数据。JavaScript没有byte类型,没有结构化的类型(s

标签: nodejs示例

本文链接地址:https://www.jiuchutong.com/biancheng/370852.html 转载请保留说明!

上一篇:Node.js中使用计时器定时执行函数详解(node-js)

下一篇:Node.js模块加载详解(nodejs引入模块)

  • 亏损企业股权转让
  • 新办营利性医疗机构是否免征土地使用税和房产税?
  • 个人经营所得税起征点是多少
  • 增值税发票必须本人去开吗
  • 会计上已资本化处理的工资企业所得税前应如何扣除?
  • 制造业税负率怎么计算
  • 暂估入库年末怎么处理
  • 物业公司物业费不开发票
  • 车保险备注栏车船税如何记账
  • 增值税发票认证平台
  • 增票未抵扣丢失怎么处理
  • 子公司是长期股权投资吗
  • 投资收益收到的现金小于投资收益
  • 退回以前年度的增值税账务处理
  • 小规模变更为一般纳税人流程
  • 财务上用替票合法么
  • 政府减免税款如何账务处理
  • 退税发票认证流程
  • 事业单位补发以后的工资
  • 卖自用轿车要缴什么税
  • 估算成本的会计要素
  • 合伙企业应纳税所得额公式是什么
  • 车辆购置税多少?
  • 企业平时计提的税费分录
  • 行政单位要纳税吗
  • 房地产开发成本和开发费用的区别
  • 减免税款怎么入账
  • 携税宝的费用可以全额抵扣吗
  • 中国工商银行社保查询
  • 建筑企业的职工由于不服管理违反规章制度
  • 公办幼儿园食堂21项制度
  • 新注册公司税务报到
  • 福利企业的增值税是多少
  • 收到运费发票是进项还是销项
  • 免税销售额需要价税分离吗
  • 欠发工资如何赔偿
  • windows 10如何清除联网记录
  • 年度利润总额是会计利润吗
  • php创建二维数组
  • php写json
  • 外贸公司付款方式有几种
  • 动态壁纸怎么设置锁屏
  • 固定资产属于资产要素吗
  • 生产经营个人所得税速算扣除数表
  • 机器学习:基于朴素贝叶斯对花瓣花萼的宽度和长度分类预测
  • php socket编程
  • 主营业务成本记错了怎么调整
  • sql merge语句
  • sql server中数据文件的扩展名是
  • 织梦二次开发教程
  • 抵扣旅客运输服务申报时填哪行
  • 发票替票该怎么做账
  • sql server触发器实例
  • 交房租会计分录怎么写好
  • 进项税留抵怎么做分录
  • 坏账准备的计提方法有哪些
  • 税盘的服务费
  • 高速公路车辆通行卡没还怎么办
  • 国有控股企业股权转让程序
  • 汽车折旧年限及残值率是多少
  • 企业搬迁补偿款免税的法律依据是什么
  • ubuntul
  • windows server2008 64位没有安装音频怎么办?
  • ubuntu18 ssh
  • linux命令和命令之间用
  • 硬盘uefi启动安装系统
  • prevsrv.exe - prevsrv是什么进程 有什么用
  • win7系统无法创建分区也无法定位
  • win10预览版21337
  • unity shaderlab
  • extjs grid设置某列背景颜色和字体颜色的方法
  • nodejs入门教程
  • [置顶]从lv2开始开挂的原勇者候悠闲的异世界生活
  • jQuery的Ajax用户认证和注册技术实例教程(附demo源码)
  • jQuery Ajax 实例代码 ($.ajax、$.post、$.get)
  • 在海口二手房需交什么税
  • 云南税务查询系统
  • 江苏省国家税务总局电子税务局
  • 2019税务系统升级
  • 广州天河东路税务局地址
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设