初步揭秘node.js中的事件
当你学习node.js的时候,Events是一个非常重要的需要理解的事情。非常多的Node对象触发事件,你能在文档API中找到很多例子。但是关于如何写自己的事件和监听,你可能还不太清楚。如果你不了解,你很快就会碰壁。那么我们如何写自己的事件和监听呢?首先而且重要的是,你要了解node.js中的events模块。
事件发布/订阅模式
事件监听器模式是一种广泛应用于一步变成的模式,是回调函数的事件化,又称发布/订阅模式。
Node自身提供的events模块,是发布/订阅模式的一个简单实现,Node中部分模块都继承自它,这个模块比前段浏览器中的大量DOM事件简单,不存在事件冒泡。它具有addListener/on(),once(),removeListener(),removeAllListeners(),emit()等基本的事件监听模式的方法实现。事件发布/订阅模式的操作极其简单:
//订阅
emitter.on("event1",function(message){
console.log(message);
})
//发布
emitter.emit("event1","I'm message");
可以看到,订阅事件就是一个高阶函数的应用。事件发布/订阅模式可以实现一个事件多个回调函数的关联,这些回调函数又称为事件侦听器。通过emit()发布事件后,消息会立即传递给当前时间的所有侦听器执行。侦听器可以很灵活的添加和删除,使得事件和具体处理逻辑可以很轻松的关联和解耦。
事件发布/订阅模式自身并无同步和异步调用的问题,但在Node中,emit()调用多半是伴随事件循环而异步触发的,所以说事件发布/订阅广发应用于异步编程。
快速浏览
加载模块,添加下面这段代码到你的js文件
require("events");
require("events").EventsEmitter
特别的,上两句代码会告诉你,以后能发出事件的所有对象基本上都是后者的实例。让我们创建一个事件对象dummy吧!
dummy.js
//基础引入
var events = require('events'); // 以后会用到
module.exports = Dummy; function Dummy() {
events.EventEmitter.call(this);
} // 继承 events.EventEmitter
Dummy.super_ = events.EventEmitter;
Dummy.prototype = Object.create(events.EventEmitter.prototype, {
constructor: {
value: Dummy,
enumerable: false
}
});
上面这段代码最终要的是,我们通过EventEmitter可以扩展自己的对象。并继承了,它所有的prototype objects,methods等等。
那么让我们假定,Dummy需要有个方法叫cooking()。如果你依照原文的话,最后肯定会报错cook不存在,所以依据原文注释我做了如下的修改。
cooking函数,功能输出我正在做...,做好之后触发事件,输出...很香!并想触发做好饭cooked事件。
Dummy.prototype.cooking=function(chicken){
var self=this;
self.chicken=chicken;
self.cook=cook;
self.cook(chicken,function(cooked_chicken){
self.chicken=cooked_chicken;
console.log(cooked_chicken);
self.emit('cooked',self.chicken);
})
return self;
}
function cook(chicken,callback){
console.log("I'm cooking"+chicken+" !");
callback(chicken+" is fragrant!");
}
那么在主js中如何调用它呢?
dummy-node.js
var Dummy=require('./dummy');
var kenny=new Dummy();
var dinner=kenny.cooking("fried_chicken");
dinner.on('cooked',function(chicken){
console.log(chicken+" Put lunch on the table!");
});
这里给出的例子中,有一点值得注意,子类有点矫枉过正,以及使用events.EventEmitter之触发了一个事件一次。如果仅仅是低触发的事件或者只有事件个数少的话,你可能想采用新的方法,比如用异步函数。
提醒
如果对一个事件添加了超过10个侦听器,将会得到一条警告。这一处设计与Node自身单线程运行有关,设计者认为侦听器太多可能会导致内存泄露,所以存在这样一条警告。调用emmitter.setMaxListeners(0);可以将这个限制去掉。另一方面,由于事件发布会引起一系列侦听器执行,如果事件相关的侦听器过多,可能存在过多占用CPU的情景。
为了处理异常,EventEmitter对象对error事件进行了特殊对待。如果运行期间的错误出发了error事件,EventEmitter会检查是否有对error事件添加过侦听器。如果添加了这个错误将会交由该侦听器处理,否则这个错误将会作为异常抛出。如果外部没有捕获这个异常,将会引起线程退出。一个健壮的EventEmitter实例应该对error事件做处理。
参考此文 http://howtonode.org/demystifying-events-in-node
初步揭秘node.js中的事件的更多相关文章
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
[摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
目录 Event Loop 是什么? Event Loop 基本解释 事件循环阶段概览 事件循环细节 timers pending callbacks poll阶段 check close callb ...
- node.js中的事件轮询Event Loop
任务队列/事件队列 "任务队列"是一个事件的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈" ...
- Node.js中的事件
var util = require("util"); //导入util模块 var events = require("events"); //导入event ...
- node.js中的事件循环机制
http://www.cnblogs.com/dolphinX/p/3475090.html
- node.js中的路由(url)初步
1.建立n4_root.js var http = require('http'); var url = require('url'); //这是node.js中自带的var router = req ...
- Node.js入门:事件机制
Evented I/O for V8 JavaScript 基于V8引擎实现的事件驱动IO. 事件机制的实现 Node.js中大部分的模块,都继承自Event模块(http://n ...
- JS基础--函数与BOM、DOM操作、JS中的事件以及内置对象
前 言 絮叨絮叨 这里是JS基础知识集中讲解的第三篇,也是最后一篇,三篇JS的基础,大多是知识的罗列,并没有涉及更难得东西,干货满满!看完这一篇后,相信许多正在像我一样正处于初级阶段的同学, ...
- node.js中process进程的概念和child_process子进程模块的使用
进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. ...
随机推荐
- 20135220谈愈敏Linux Book_4
进程调度 进程:程序的运行态表现形式 进程调度程序:确保进程能有效工作的一个内核子系统,决定将哪个进程投入运行.何时运行以及运行多长时间,在可运行态进程之间分配有限的处理器时间资源. 最大限度的利用处 ...
- 【MyEclipse 2015】 逆向破解实录系列【1】(纯研究)
声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...
- C#中的yield return与Unity中的Coroutine(协程)(上)
C#中的yield return C#语法中有个特别的关键字yield, 它是干什么用的呢? 来看看专业的解释: yield 是在迭代器块中用于向枚举数对象提供值或发出迭代结束信号.它的形式为下列之一 ...
- sublime2的一些基本常用的操作
1.全局搜 ctrl shift f 如果你的快捷键有冲突的话,那么你在find的菜单中有find in file这个中找.
- Fluent NHibernate关系映射
1.好处:Fluent NHibernate让你不再需要去写NHibernate的标准映射文件(.hbm.xml), 方便了我们的代码重构,提供了代码的易读性,并精简了项目代码 实现: (1).首先我 ...
- css动画之波纹
样式定义: #ContactAbout { height: auto; position: relative; overflow: hidden; } #sectioncontact { displa ...
- Linq之常见关键字
目录 写在前面 系列文章 常见关键字 总结 写在前面 前面的几篇文章算是对linq的铺垫,从本篇开始将进行linq的语法及实践. 系列文章 Linq之Lambda表达式初步认识 Linq之Lambda ...
- 转:Oracle中merge into的使用
最近项目上使用Oracle的Merge,所以找来一下资料学习了解. 该命令使用一条语句从一个或者多个数据源中完成对表的更新和插入数据. ORACLE 9i 中,使用此命令必须同时指定UPDATE 和I ...
- CXF 自定义拦截器
此例子来自apache cxf sample. /** * Licensed to the Apache Software Foundation (ASF) under one * or more ...
- Spring-如何实现事物管理的
事务的实现方式 实现方式共有两种:编码方式:声明式事务管理方式.基于AOP技术实现的声明式事务管理,实质就是:在方法执行前后进行拦截,然后在目标方法开始之前创建并加入事务,执行完目标方法后根据执行情况 ...