zoukankan      html  css  js  c++  java
  • 初步揭秘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

  • 相关阅读:
    【转载】兼容php5,php7的cURL文件上传示例
    解决CURL 请求本地超时
    PHP 二维数组根据某个字段排序
    JS监听输入框值变化兼容 onpropertychange、oninput
    PHP AES的加密解密-----【弃用】
    PHP 开发API接口签名验证
    Python 逐行修改txt每条记录的内容
    Python 修改电脑DNS
    带小数点时间分钟转换
    Python 判断字符串是否为数字
  • 原文地址:https://www.cnblogs.com/yixiaoheng/p/let-us-learn-nodejs-together-4.html
Copyright © 2011-2022 走看看