初步揭秘node.js中的事件

时间:2022-11-01 01:14:41

当你学习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中的事件的更多相关文章

  1. 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick

    [摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...

  2. 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick

    目录 Event Loop 是什么? Event Loop 基本解释 事件循环阶段概览 事件循环细节 timers pending callbacks poll阶段 check close callb ...

  3. node.js中的事件轮询Event Loop

    任务队列/事件队列 "任务队列"是一个事件的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈" ...

  4. Node.js中的事件

    var util = require("util"); //导入util模块 var events = require("events"); //导入event ...

  5. node.js中的事件循环机制

    http://www.cnblogs.com/dolphinX/p/3475090.html

  6. node.js中的路由(url)初步

    1.建立n4_root.js var http = require('http'); var url = require('url'); //这是node.js中自带的var router = req ...

  7. Node.js入门:事件机制

    Evented I/O for V8 JavaScript     基于V8引擎实现的事件驱动IO.   事件机制的实现     Node.js中大部分的模块,都继承自Event模块(http://n ...

  8. JS基础--函数与BOM、DOM操作、JS中的事件以及内置对象

       前   言 絮叨絮叨 这里是JS基础知识集中讲解的第三篇,也是最后一篇,三篇JS的基础,大多是知识的罗列,并没有涉及更难得东西,干货满满!看完这一篇后,相信许多正在像我一样正处于初级阶段的同学, ...

  9. node.js中process进程的概念和child_process子进程模块的使用

    进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. ...

随机推荐

  1. form-line 样式 让 两个控件在同一个水平位置

    <div class="row"> <div> <label class="form-inline">参加单位:<in ...

  2. 关于String对象的比较

    1.String对象的比较 String 是一个常量,从String类中的代码可以看出.String类内部是通过char数组来存储字符串,这个char数组是被声明成final的. // Java中只要 ...

  3. Cookies和Session的区别

    原文:http://www.cnblogs.com/lijihong/p/4743818.html 今天主要学习了Cookies和Session,网络上关于这方面的知识可谓很多,让人眼花缭乱,在此作一 ...

  4. &lbrack;转载&rsqb; C&plus;&plus;位运算:将一个4字节整数的二进制表示中的001替换为011

    #include <iostream> #include <assert.h> /** * Key: * * get someone bit: num & (mode1 ...

  5. Notification用法

    String message = "You should click come back now. It is time out more than 10 minutes."; / ...

  6. 读取tomcat下的文件夹路径

    背景:测试的为了每次部署时清缓存,将temp文件夹也删了,导致系统中有些excel导出功能用不了. 解决:新建一个监听文件,在系统启动时,判断temp文件夹是否存在,不存在就新建. temp文件夹的作 ...

  7. qt 共享内存&lpar;QSharedMemory&rpar;

    ——————————————————写入部分—————————————————— (本次程序基于控制台程序) 首先 使用共享内存得召唤一下: #include <QSharedMemory&gt ...

  8. Gridview实现银行选择列表

    [MainActivity.java] package com.example.activitydemo; import android.os.Bundle; import android.view. ...

  9. &lbrack;置顶&rsqb; 强制访问控制内核模块Smack

    Smack(Simplified Mandatory Access Control Kernel)是Casey Schaufler[15]于2007年在LSM基础上实现的Linux强制访问控制安全模块 ...

  10. 【Git之旅】2&period;Git对象

    1.块(blob)对象 (1)文件的每一个版本表示为一个块 (2)二进制大对象(binary large object)的缩写,是计算机领域的常用术语,用来指代某些可以包含任意数据的变量或文件,同时其 ...