nodeJS - 3 - Events事件

Events 事件模块

说明

大多数 Node.js 核心 API 都采用异步事件驱动架构,其中某些类型的对象(触发器)会周期性的触发命名事件来调用函数对象(监听器),所有能触发事件的对象都是 EventEmitter 类的实例,允许将一个或者多个函数绑定到会被对象触发的命名事件上

EventEmitter 会按照监听器函数的注册顺序同步的调用所有监听器,所以需要确保事件的正确排序且避免竞争条件或逻辑错误,监听器函数中可以使用 setImmediate() 或者 process.nextTick() 方法切换到异步操作模式

参考

    // 获取事件发生器的构造函数
    const Emitter = require('events').EventEmitter;

    // 创建事件发生器实例,也就是消息中心,用来注册和触发事件(订阅和发布)
    const emitter = new Emitter();

    // 事件响应函数
    function handle1(some) {
        console.log('handle - ', some);
    }
    function handle2(some) {
        console.log('同步的', some);
        process.nextTick(function () {
            console.log('nextTick', some);
        })
        setImmediate(() => {
            console.log('setImmediate', some);
        })
    }    

    // on 注册事件,指定回调函数
    emitter.on('test', handle1);
    emitter.on('test', handle2)

    // emit 触发事件
    setTimeout(function () {
        console.log('start emit');
        emitter.emit('test', 'test data');
        console.log('end emit');
    }, 1000);

    /*
        start emit
        handle -  test data
        同步的 test data
        end emit
        nextTick test data
        setImmediate test data
    */

Event Emitter 接口可以部署在任意对象上,使得这些对象也能够订阅和发布消息

    // 获取事件发生器的构造函数
    const Emitter = require('events').EventEmitter;

    // 创建构造函数
    function Test() {
        this.name = 'test';
    }

    /*
        使构造函数的原型继承事件发生器的原型方法
        Object.create(a) 以 a 为原型创建对象
        将事件发生器添加到构造函数原型对象的原型上,可以方便构造函数原型上继续添加方法(注意不要将原型对象覆盖)
    */ 
    // Test.prototype.__proto__ = Emitter.prototype;
    Test.prototype = Object.create(Emitter.prototype); 

    Test.prototype.say = function () {
        console.log(this.name);
    }

    // 创建实例
    const test = new Test();

    // 事件响应函数
    function handle(some) {
        console.log('handle - ', some);
    }

    // 注册事件
    test.on('test', handle);

    // 触发事件
    setTimeout(function () {
        console.log('start emit');
        test.emit('test', 'test extend');
        console.log('end emit');
    }, 1000);

Node.js 内置工具 util 模块提供 inherits 方法,用于继承

    const Emitter = require('events').EventEmitter;
    const util = require('util');

    function Test() {
        this.name = 'test name';

        this.on('newListener', function (listener) {
            console.log('listener: ', listener);
        })
    }

    Test.prototype.init = function () {
        this.emit('open', 'init open');

        setTimeout(() => {
            this.emit('close', 'init close');
        }, 1000)
    }

    util.inherits(Test, Emitter); // Emitter 的接口继承到 Test 上

    const test = new Test();

    function handle(text) {
        console.log(text);
    }

    test.on('open', handle);
    test.on('close', handle);

    test.init();

Event Emitter 实例方法

  1. on() 给事件添加监听器函数,添加多个事件监听器会按照添加顺序依次执行
  2. once() 给事件添加监听器函数,只执行一次
  3. addListener() 与 on 一样
  4. emit() 按照监听器的注册顺序同步地调用每个注册在此事件下的监听器,并提供参数
  5. listeners() 返回名某个事件下的监听器数组
  6. removeListener() 两个参数:eventName, listener ,移除某个事件下的指定监听器
  7. removeAllListeners() 移除某个事件下的所有监听函数
  8. setMaxListeners() 修改指定实例的事件监听器上限
  9. getMaxListeners() 返回监听器限制值
  10. prependListener() 添加事件监听器到指定事件的开头
  11. prependOnceListener() 添加事件监听器到指定事件的开头,只执行一次
  12. listenerCount() 返回某个事件的监听器数量
  13. eventNames() 返回已注册的事件名的数组
    const Emitter = require('events').EventEmitter;

    const emitter = new Emitter();

    function handle (f) {
        return function (text) {
            console.log(f, text);
        }
    }

    // once 指定事件的监听函数只执行一次
    emitter.once('onceEvent', handle('once')); 

    // on 指定事件的监听函数
    emitter.on('onceEvent', handle('on')); 

    // addListener 与 on 一样
    emitter.addListener('onceEvent', handle('addListener')); 

    // listeners 返回同一个事件下回调函数的数组
    const listeners = emitter.listeners('onceEvent'); 
    console.log(listeners); // length 3

    // emit 触发事件
    emitter.emit('onceEvent', 'emit1');  
    /*
        once emit1
        on emit1
        addListener emit1
    */

    emitter.emit('onceEvent', 'emit2');
    /*
        // once 只执行一次,所以没有响应
        on emit2
        addListener emit2
    */ 

    // removeAllListeners 移除某个事件的所有监听函数
    emitter.removeAllListeners('onceEvent'); 
    emitter.emit('onceEvent', 'emit3'); // 没响应

    function handle2(text) {
        console.log('handle2 ', text);
    }
    function handle3(text) {
        console.log('handle3 ', text);
    }
    function handle4(text) {
        console.log('handle4 ', text);
    }
    function handle5(text) {
        console.log('handle5 ', text);
    }

    emitter.on('twiceEvent', handle2);
    emitter.on('twiceEvent', handle3);

    // prependListener 添加事件监听器到指定事件的开头
    emitter.prependListener('twiceEvent', handle4); // 先执行

    // prependOnceListener 添加事件监听器到指定事件的开头,只执行一次
    emitter.prependOnceListener('twiceEvent', handle5); 

    // removeListener 移除某个事件的某个监听函数
    emitter.removeListener('twiceEvent', handle2); 
    emitter.emit('twiceEvent', 'emit4'); // handle3  emit4; handle2 不响应

    // setMaxListeners 修改指定实例的事件监听器上限
    emitter.setMaxListeners(20); 

    // 返回监听器限制值
    emitter.getMaxListeners(); // 20

    // listenerCount 返回某个事件的监听器数量
    emitter.listenerCount('twiceEvent') // 2 

    // eventNames 返回已注册的事件名的数组
    emitter.eventNames() // [ 'twiceEvent' ]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值