Node中大量运用了事件回调,所以Node对事件做了单独的封装。所有能触发事件的对象都是 EventEmitter 类的实例,所以上一篇我们提到的文件操作的可读流、可写流等都是继承了 EventEmitter。当然我们也可以自定义具有事件行为的自定义对象,仅需要对其继承即可。

继承EventEmitter

node的events模块封装了EventEmitter类型,此类型里面封装了事件注册、触发等API。

// 引入events模块
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {
constructor(opt) {
super(opt);
}
} // 创建事件对象实例。
const myEmitter = new MyEmitter(); // 注册event事件,event是事件名字,最好符合以驼峰命名规范。
myEmitter.on('event', () => {
console.log('触发了一个事件!');
}); // 触发event事件
myEmitter.emit('event');

给回调函数传递参数

emit()方法触发事件的同时,还可以给回调函数传递参数。

// 引入events模块
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {
constructor(opt) {
super(opt);
}
} // 创建事件对象实例。
const myEmitter = new MyEmitter(); // 注册event事件,event是事件名字,最好符合以驼峰命名规范。
myEmitter.on('event', (a, b) => {
console.log('event: %s, %s', a, b);
}); // 触发event事件,并传递参数a、b
myEmitter.emit('event', 'aicoder.com', '全栈实习');

错误处理的约定

当 EventEmitter 实例中发生错误时,会触发一个 'error' 事件。 这在 Node.js 中是特殊情况。

如果 EventEmitter 没有为 'error' 事件注册至少一个监听器,则当 'error' 事件触发时,会抛出错误、打印堆栈跟踪、且退出 Node.js 进程。

const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// 抛出错误,并使 Node.js 崩溃

为了防止 Node.js 进程崩溃,可以在 process 对象的 uncaughtException 事件上注册监听器.

const myEmitter = new MyEmitter();

// 给nodejs的进程增加未捕获异常的处理,防止程序崩溃
process.on('uncaughtException', (err) => {
console.error('有错误');
}); myEmitter.emit('error', new Error('whoops!'));
// 打印: 有错误

只处理事件一次

on()方法可以注册事件处理程序,而且是每次emit()触发事件,都会被执行。但是用once()注册的事件,仅执行一次。例如:

// 引入events模块
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {
constructor(opt) {
super(opt);
}
} const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// 打印: 1
myEmitter.emit('event');
// 忽略

实战案例

做一个应用时,我们需要在应用启动之前或者启动之后,给其他的开发人员提供一些可以注册处理程序的钩子,可以用事件的方式实现。其实本质就是发布订阅模式。

'use strict';

const EventEmitter = require('events');

class Application extends EventEmitter {
constructor(opt) {
super(opt);
this.on('error', err => {
console.log('应用程序出错了!');
});
} init() {
// 触发预初始化事件
this.emit('preInit'); // ... 默认的初始化代码 // 初始化事件
this.emit('init');
} start() {
// 初始化服务器
this.init();
} } /**/
var app = new Application();
app.on('init', () => {
console.log('初始化!');
});
app.on('preInit', () => {
console.log('pre init');
});
app.start();

总结

Node中的事件处理封装很简单易用,跟jQuery的事件系统非常类似。其实自己实现一套事件系统也不难,核心思想就是:发布订阅(观察者)模式。


老马免费视频教程

返回教程列表首页

github地址:https://github.com/malun666/aicoder_node

 

Node入门教程(10)第八章:Node 的事件处理的更多相关文章

  1. Linux pwn入门教程(10)——针对函数重定位流程的几种攻击

    作者:Tangerine@SAINTSEC 本系列的最后一篇 感谢各位看客的支持 感谢原作者的付出一直以来都有读者向笔者咨询教程系列问题,奈何该系列并非笔者所写[笔者仅为代发]且笔者功底薄弱,故无法解 ...

  2. ArcGIS for Desktop入门教程_第八章_Desktop学习资源 - ArcGIS知乎-新一代ArcGIS问答社区

    原文:ArcGIS for Desktop入门教程_第八章_Desktop学习资源 - ArcGIS知乎-新一代ArcGIS问答社区 1 学习资源 用户在学习和应用过程中,可以参考的资源如下: 1. ...

  3. D3.js的v5版本入门教程(第八章)—— 坐标轴

    D3.js的v5版本入门教程(第八章) D3中没有现成的坐标轴图形,需要我们自己用其他组件拼凑而成.D3中提供了坐标轴组件,使得我们在SVG中绘制一个坐标轴变得像添加一个普通元素那样简单 为了表绘制一 ...

  4. Node入门教程(2)第一章:NodeJS 概述

    Node 概述 什么是 Node Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js us ...

  5. Node入门教程(1)目录

    aicoder.com 全栈实习之简明 Node 入门文档 aicoder.com 线下实习: 不 8000 就业,不还实习费. 如果需要转载本文档,请联系老马,Q: 515154084 JS基础教程 ...

  6. Node入门教程(8)第六章:path 模块详解

    path 模块详解 path 模块提供了一些工具函数,用于处理文件与目录的路径.由于windows和其他系统之间路径不统一,path模块还专门做了相关处理,屏蔽了彼此之间的差异. 可移植操作系统接口( ...

  7. 《Node入门》读书笔记——用Node.js开发一个小应用

    Android APP的开发告一段落,一个稳定的.实现了基本功能的APP已经交付用户使用了!我和老板交流了下,接下来准备转战Node.js了,而且一部分前端的功能也要做进去!哈哈哈~~~接下来要朝一个 ...

  8. ASP.NET Core 入门教程 10、ASP.NET Core 日志记录(NLog)入门

    一.前言 1.本教程主要内容 ASP.NET Core + 内置日志组件记录控制台日志 ASP.NET Core + NLog 按天记录本地日志 ASP.NET Core + NLog 将日志按自定义 ...

  9. ABP入门教程10 - 展示层实现增删改查-控制器

    点这里进入ABP入门教程目录 创建控制器 在展示层(即JD.CRS.Web.Mvc)的Controllers下新建一个控制器CourseController.cs using Abp.Applicat ...

随机推荐

  1. 洛谷 P1474 货币系统 Money Systems(经典)【完全背包】+【恰好装满的最大方案数量】

    题目链接:https://www.luogu.org/problemnew/show/P1474 题目描述 母牛们不但创建了它们自己的政府而且选择了建立了自己的货币系统.由于它们特殊的思考方式,它们对 ...

  2. [漏洞分析]thinkcmf 1.6.0版本从sql注入到任意代码执行

    0x00 前言 该漏洞源于某真实案例,虽然攻击没有用到该漏洞,但在分析攻击之后对该版本的cmf审计之后发现了,也算是有点机遇巧合的味道,我没去找漏洞,漏洞找上了我XD thinkcmf 已经非常久远了 ...

  3. Alpha冲刺随笔二:第二天

    课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(十天冲刺) 团队名称:葫芦娃队 作业目标:在十天冲刺里对每天的任务进行总结. 随笔汇总:https://www.cnblogs ...

  4. UTF8编码的Base64解密 MSSQL实现

    GO CREATE FUNCTION [dbo].[c_GetUTF8Code] ( @char Nchar ) RETURNS int AS --UTF8转码 BEGIN Declare @Code ...

  5. 更新 是 可用的 针对 安卓 软件开发包和工具 Updates are available for android software development packages and tools

    作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com E-mail: 313134555 @qq.com 更新 是 可用的 针对 安卓 软件开发包和工 ...

  6. APIO2018 铜滚记

    「一旦闭上双眼,就昏昏欲睡」「仿佛与这个世界的联系,被瞬间切断」「可是,负罪感与背德感又会在黑暗中将我吞噬」「即使这样,却也无法与身体的疲惫抗衡」 「如果,这些东西也无法让意识的存在稳定下来的话」「那 ...

  7. 洛谷.1782.旅行商的背包(背包DP 单调队列)

    题目链接(卡常背包) 朴素的多重背包是: \(f[i][j] = \max\{ f[i-1][j-k*v[i]]+k*w[i] \}\),复杂度 \(O(nV*\sum num_i)\) 可以发现求\ ...

  8. If you sleep now,you will have a dream. If you study now,you will achieve your dream.

    If you sleep now,you will have a dream. If you study now,you will achieve your dream. 我开始思考,What's m ...

  9. Cocos2dx使用TextField实现输入框

    游戏login的时候必须要求玩家输入用户名.密码,还要可以删除. cocostudio画一个textfield,直接读入好了: textField类,继承读取的widget. local textFi ...

  10. PHPMailer 使用方法(支持群发):

    一.下载函数包 地址:https://github.com/PHPMailer/PHPMailer 二.测试服务器环境 通过phpinfo()函数打印出是否支持Sockets(Socket属于php的 ...