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. webstorm 格式化代码及常用快捷键

    mac 下 webstorm 格式化代码的快捷键 Option+Command+l windows 下 webstorm 格式化代码的快键键 Ctrl+Alt+l centOS 下webstorm 格 ...

  2. 洛谷 P1507 NASA的食物计划 【二维费用背包】 || 【DFS】

    题目链接:https://www.luogu.org/problemnew/show/P1507 题目背景 NASA(美国航空航天局)因为航天飞机的隔热瓦等其他安全技术问题一直大伤脑筋,因此在各方压力 ...

  3. ESLint + lint-staged 禁用老项目中的es6

    前言 ESLint作为插件化的javascript代码检测工具,为我们的平时的开发保驾护航,好处就不多说了详情查看官网. 问题 有这么一个五年前开发的老项目,机缘巧合到了我们这边来维护. 项目是zep ...

  4. <<c专家编程>>笔记

    C专家编程摘录 c操作符的优先级 有时一些c操作符有时并不会像你想象的那样工作. 下方表格将说明这个问题: 优先级问题 表达式 期望的情况 实际情况 . 优先级高于* *p.f (*p).f *(p. ...

  5. [HDU5685]Problem A

    来源: 2016"百度之星" - 资格赛(Astar Round1) 思路: 首先处理出所有前缀的哈希$f$,对于所有的询问$[a,b]$,答案即为$\frac{f[b]}{f[a ...

  6. 使用xlrd模块操作Excel

    table = data.sheets()[] table = data.sheet_by_index() print(table) #获取正行或是整列的值 con = table.row_value ...

  7. IE6条件下的bug与常见的bug及其解决方法

    1.IE6条件下有双倍的margin 解决办法:给这个浮动元素增加display:inline属性 2. 图片底部有3像素问题 解决办法:display:block;或者vertical-align: ...

  8. C++ 代码格式化工具Astyle

    1.下载Asyle程序. win版本:https://sourceforge.net/projects/astyle/ 2.将bin/AStyle.exe拷到源码目录中,在命令行终端执行. AStyl ...

  9. java中关于AtomicInteger的使用

    在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字.而AtomicInteger则通过一种线程安全的加减操作接口.咳哟参考我之前写的一篇 ...

  10. 修改文件夹的protection level之后,哪个job会来执行re-stripe的操作呢?

    有下面的一些job可能参与其中的,他们的描述如下: AutoBalance,AutoBalanceLin - Balances free space in the cluster. The goal ...