我爱编程

Node.js组成及Events模块

2017-01-10  本文已影响97人  有个水友

1 Node.js的模块和包

1.1模块

Node.js本身提供许多模块,每个模块实现一种功能,如文件操作模块fs,构建HTTP服务的http模块等,每个模块都是一个javascript文件,可以自己编写模块。

每一个Node.js都是一个Node.js模块,包括JavaScript文件(.js)、JSON文本文件(.json)和二进制模块文件(.node

1.1.1 模块的使用

模块内使用module.exportsexports对外提供接口,便于在其他模块中引入要使用的模块,新建模块module.js,并对外提供接口。

使用exports提供接口

function hello() {
    console.log("Hello");
}

function world() {
    console.log("World");
}

exports.hello = hello;
exports.world = world;

使用module.exports提供接口

function Hello() {
    this.hello = function() {
        console.log("Hello");
    };

    this.world = function() {
        console.log("World");
    };
}

module.exports = Hello;
1.1.2 引用模块

使用require()引用创建的模块,参数是模块的路径。

引用exports提供接口的模块

var hello = require("./test.js");

hello.hello();  //==> Hello
hello.world();  //==> World

引用module.exports提供接口的模块

//module.exports导出的是Hello函数,将其保存到Test变量中
var Test = require("./test.js");

//将Test()当做构造起函数,创建对象来使用
var demo = new Test();
demo.hello();    //==> Hello
demo.world();  //==> World

1.2 module.exportsexports区别

每个模块中都有一个module对象,module是当前模块的一个引用。module.exports对象是由Module系统构建的,exports可以看做module.exports对象的引用。

require()一个模块时,module.exports的值为准,在有的情况下module.exportsexports的值不同。

// module.exports和exports相同的情况
var m = {};        // 表示 module
var e = m.e = {};  // e 表示 exports, m.e 表示 module.exports

m.e.a = 5;
e.b = 6;

console.log(m.e);  // Object { a: 5, b: 6 }
console.log(e);    // Object { a: 5, b: 6 }
// module.exports和exports不同的情况
var m = {};        // 表示 module
var e = m.e = {};  // e 表示 exports, m.e 表示 module.exports

m.e = { c: 9 };    // m.e(module.exports)引用的对象被改了
e.d = 10;

console.log(m.e);  // Object { c: 9 }
console.log(e);    // Object { d: 10 }

1.2 包

包可以将多个具有依赖关系的模块组织在一起,将多个模块封装,便于管理。

Node.js采用CommonJS规范,一个javascript文件就是一个模块,包是一个文件夹,包内必须包含一个名为package.json的JSON文件
包内bin文件夹内存放二进制文件,lib文件夹存放javascript文件,doc文件夹存放文档,test文件夹存放单元测试。

1.2.1包的目录

包的目录必须包含package.json文件,CommonJS用来描述包,应该包含以下字段:

实例

{
    "name": "Kyxy",
    "description": "Kyxy test package.",
    "version": "0.1.0",
    "keywords": [
        "kyxy",
        "nodejs"
     ],
    "maintainers": [{
        "name": "test",
        "email": "test@kyxy.com"
    }],
    "contributors": [{
        "name": "test",
        "web": "http://www.kyxy.com/"
    }],
    "bugs": {
        "mail": "test@kyxy.com",
        "web": "http://www.kyxy.com/"
    },
    "licenses": [{
        "type": "Apache License v2",
        "url": "http://www.apache.org/licenses/apache2.html"
    }],
    "repositories": [{
        "type": "git",
        "url": "http://github.com/test/test.git"
    }],
    "dependencies": { 
        "webkit": "1.2",
        "ssl": { 
            "gnutls": ["1.0", "2.0"],
            "openssl": "0.9.8"
        }
    }
}

1.3 npm包管理工具

npm是Node.js的包管理工具,npm定义了包依赖关系标准,使用npm下载第三方包和管理本地下载的第三方包

查询包信息
npm info express
安装包
sudo npm install express
更新包
sudo npm update express
卸载包
sudo npm uninstall express


2 Events模块

Node.js中,许多对象会发出事件:fs.readStream 打开一个文件时会发出一个事件。所有发出的事件对象都是events.EventEmitter的实例,可以通过require("events");获得events模块。

事件命名推荐使用驼峰命名法。将函数添加到对象,对象发出事件时,相应函数被执行(这些函数被称为监听器);先将函数赋予对象(设为监听器),在对象发出事件时调用该函数

2.1 Class: events.EventEmitter

通过require("events").EventEmitter获取 EventEmitter类。当EventEmitter对象遇到错误时,触发error事件

error事件在Node.js中是一种特殊事件,(如果没有设置error事件触发的监听器),默认打印出栈跟踪器,并退出程序。

2.2 添加监听器

为事件添加监听器有两种方法,作用完全相同:参数事件(event),处理函数(listener)

//import http module
var http = require("http");
//create a http server
var server = http.createServer();

//bind a listener for server`s request Event
server.on("request", function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write("Tracy");
    console.log("Kyxy");
    res.end();
});

//listen ip:127.0.0.1 port:1337, if requested, execute the listener function
server.listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

运行上述代码,在浏览器地址栏输入127.0.0.1:1337,可以看到Tracy,同时控制台输出Kyxy

2.3 只执行一次的监听器

使用emitter.once(event, listener)方法绑定的事件监听器只会执行一次,然后事件被删除。

var http = require('http');
var server = http.createServer();

// 为request事件绑定处理函数,事件只会执行一次
server.once('request', function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write('shiyanlou');
    console.log('shiyanlou');
    res.end();
});

server.listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

运行上述代码,在浏览器地址栏输入127.0.0.1:1337,可以看到Tracy,同时控制台输出Kyxy再刷新页面,就不会再显示,因为事件只会执行一次。

2.4 移除监听器

使用emitter.removeListener(event, listener)方法移除为对象的request事件绑定的处理函数。

//import http module
var http = require("http");
//create a http server
var server = http.createServer();

function callback(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write("Hello World");
    console.log("Hello World");
    res.end();
}

//bind a listener for server`s request Event
server.on("request", callback);

//remove a listener for server`s request Event
server.removeListener("request", callback);

server.on("request", function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/json' });
    res.write("I`m back");
    console.log("LMD");
    res.end();
});

//listen ip:127.0.0.1 port:1337, if requested, execute the listener function
server.listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

运行上述代码,在浏览器地址栏输入127.0.0.1:1337,可以看到Im back,同时控制台输出LMD,但是没有Hello World,因为监听器callback`被移除了。

2.4 移除所有监听器

使用emitter.removeAllListeners([event]),移除对象上监听event事件的所有监听器

//import http module
var http = require("http");
//create a http server
var server = http.createServer();

function talk(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write("haha");
    console.log("xixi");
    res.end();
}function fruit(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write("apple");
    console.log("leomon");
    res.end();
}

//bind  listeners for server`s request Event
server.on("request", talk);
server.on("request", fruit)
//remove  listeners from server`s request Event
server.removeAllListeners("request");

server.on("request", function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/json' });
    res.write("I`m back");
    console.log("LMD");
    res.end();
});

//listen ip:127.0.0.1 port:1337, if requested, execute the listener function
server.listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

移除绑定在server上的所有事件监听器,所以只显示Im back,输出LMD`。

2.5 设置监听器的最大绑定数

emitter.setMaxListeners(n)可以设置同一事件可以绑定的监听器的最大数目,默认情况下,超过10个就会提示警告信息(可以帮助找到内存泄漏的地方),不是所有的事件触发器都限制在10个,可以通过这个方法设置,如果设置为0就是无限制

2.6 自定义事件

使用emitter.emit(event, [arg1], [arg2], [...]),可以触发自定义事件。

//import http module
var http = require("http");
//create a http server
var server = http.createServer();

server.on("myevent", function(arg) {
    console.log(arg);
});

server.emit("myevent", "Kyxy");

server.on("request", function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write("Tracy");
    res.end();
});

//listen ip:127.0.0.1 port:1337, if requested, execute the listener function
server.listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

2.7 查看事件绑定的监听器个数

使用events.EventEitter.listenerCount(emitter, event)可以查看事件监听器的数量。

var http = require("http");
var events = require("events");
var server = http.createServer();

server.on("request", function(req, res) {
    res.writeHead(200, {"Content-Type": "text/plain"});
    res.write("kyxy");
    console.log("kyxy");
    res.end();
});

server.on("request", function(req, res) {
    res.writeHead(200, {"Content-Type": "text/plain"});
    res.write("Tracy");
    console.log("Tracy");
    res.end();
});

server.listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

var num = events.EventEmitter.listenerCount(server, "request");
console.log(num); //2

控制台界面输出了数字2,因为server绑定了两个监听器到'request'事件。

上一篇下一篇

猜你喜欢

热点阅读