核心模块
今天就是第三讲了,上两篇博客说了下node的基本概念,包括异步,事件式编程模块和包,以及调试。那现在就要深入讲解node.js的核心模块了噢噢。在说node的核心模块的前提我先列出我所要讲的知识点吧
1. 全局对象
2. 常用工具util
3. 深入事件驱动event对象
4. 文件系统fs模块
5. 深入了解服务器与客户端
不少了吧这片博客一下子是说不完这么多的,所以我想把这部分作为几篇博客来进行描述。。。。
好了说了这么多那就进入正题吧
全局对象
JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可
以在程序的任何地方访问,即全局变量。在浏览器 JavaScript 中,通常 window 是全局对象,而 Node.js中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global对象的属性。例如:console process 等,下边我们会挨个介绍
全局对象和变量
global 最根本的作用是作为全局变量的宿主。按照 ECMAScript 的定义,满足以下条
件的变量是全局变量:
1最外层定义的变量;
1局对象的属性;
1隐式定义的变量(未定义直接赋值的变量)。
呵呵你在node里边是不可能把变量定义到最外边的,你会问我为什么?因为所有用户代码都属于当前模块。而模块本身不是最外层上下文。
在这里我介绍两个全局的对象是process和我们常用到的console
Process
process 是一个全局变量,即 global 对象的属性。它用于描述当前 Node.js进程状态的对象,提供了一个与操作系统的简单接口。通常在你写本地命令行程序的时候,少不了要和它打交道
1. process.argv是命令行参数数组,第一个元素是 node, 第二个元素是脚本文件名,从第三个元素开始每个元素是一个运行参数。
console.log(process.argv);
2. process.stdout是标准输出流,通常我们使用的 console.log() 向标准输出打印字符,而process.stdout.write() 函数提供了更底层的接口。
process.stdout.write("试试看咯")
3. process.stdin是标准输入流,初始时它是被暂停的,要想从标准输入读取数据,你必须恢复流,并手动编写流的事件响应函数。
process.stdin.resume();
process.stdin.on('data',function(data){
process.stdout.write("redadfrom console.log:"+data.toString());
})
4. process.nextTick(callback)的功能是为事件循环设置一项任务, Node.js 会在下次事件循环调响应时调用 callback
这句话有些初学者有可能不明白了?那我用以前的例子说下咯
我们第一篇博客就说了我们的js是单线程的,还记得我说的i/o吗?如果这个事件占用大量的cpu时间,执行事件循环中的下一个事件就需要等待很久,因此node。Js为了缩短每个时间的执行时间。Porcess.nextTick()就诞生了把复杂的工作进行拆分变成较小的事件驱动。 理论解释完了如果还不懂那我只好上代码咯
代码如下:
function a(args, callback) {
b(args);
callback();
}
a(function onEnd() {
c();
});
我们定义了一个名字为a的函数虽然不规范了点,就这么看吧。如果b函数和c函数都是i/o你想想看js又是单线程的,当我调用a函数时候会执行b函数对吧,然后执行我的回调函callback,但是b和c函数都是i/o需要事件等待的那cpu是不是需要等待很长时间啊!!为了避免这种情况我们用process.nextTick();函数应该怎么解决呢?代码如下
function a(args, callback) {
b(args);
process.nextTick(callback);
}
a(function onEnd() {
c();
});
在这里就不要考虑用setTimetout(fn,0)了因为这个函数和nextTick方法效率上差多了。
当然process不仅仅是这些方法,它还有很多噢噢platform ,pid,execpath,memoryUsage等等,想要访问更多点击该链接http://nodejs.org/api/process.html
好了到这里我们的process对象常用的方法就介绍到这里了该介绍console对象了,
Console
console 用于提供控制台标准输出,它是由 Internet Explorer 的 JScript 引擎提供的调试工具,后来逐渐成为浏览器的事实标准。 Node.js 沿用了这个标准,提供与习惯行为一致的console 对象,用于向标准输出流(stdout)或标准错误流(stderr)输出字符
1. console.log():向标准输出流打印字符并以换行符结束。 console.log 接受若干个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则以类似于 C 语言 printf() 命令的格式输出。第一个参数是一个字符串,如果没有参数,只打印一个换行
2. console.error():与 console.log() 用法相同,只是向标准错误流输出。
3. console.trace():向标准错误流输出当前的调用栈。
好了console就介绍到这里了是不是感觉被骗的感觉这些方法我都知道诶!!哈哈。。你之所以知道是你在浏览器里边常用了说到这里我们的全局对象就要over万事咯。。。当当现在我们要进入下一个环节了那就是我们常用的util工具
常用的util工具
util 是一个 Node.js 核心模块,提供常用函数的集合,用于弥补核心 JavaScript 的功能过于精简的不足比如js里边的继承方式,对象转化字符串了等等。。
util.inherits(constructor,superConstructor)
我上边说了javascript精简了,但是没有继承的函数,那继承函数谁来弥补呀,那就是inherits这个方法咯
首先我们导入我们的util包
var util=require("util");
function Pet(){
this.name='cat';
this.base=1990;
this.sayHello=function(){
console.log('喵'+this.name);
}
}
Pet.prototype.showName=function(){
console.log(this.name);
}
function Dog(){
this.name='dog';
}
util.inherits(Dog,Pet);
var objPet=new Pet();
objPet.showName();
objPet.sayHello();
console.log(objPet);
var dog=new Dog();
dog.showName();
//dog.SayHello();
console.log(dog);
dog 仅仅继承了 Pet 在原型中定义的函数,而构造函数内部创造的 base 属性和sayHello 函数都没有被 Sub 继承。同时,在原型中定义的属性不会被 console.log 作
为对象的属性输出。
说到这里我问你个问题你见过用js怎么将对象转化成字符串的方法吗?你肯定会回答通过parse()和stringify()方法,但是这些方法是js封装好的方法吗?回答肯定是不是的他是第三放写的,索性不纳入js原生法。就是因为原生没有node,为了提供字符串和对象互转所以inspect方法才面世。哈哈。。。
util.inspect
util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换
为字符串的方法,通常用于调试和错误输出。它至少接受一个参数 object,即要转换的对象。
我在这里先简单的描述下各个参数
第一个object我就不多说了,就是被转化的对象
showHidden:是个bool值,如果设置为true的情况下他会显示更多被隐藏的对象信息
depth:通过字面也不难理解就是遍历该对象的层级,默认遍历是2层噢噢。。
colors:这个对我来说是个蛋疼的参数,就是在终端输入的时候显示一个高亮效果,显得漂亮点,可读性高点,就这么个功能。是不是很蛋疼有么有。
除了以上我们介绍的几个函数之外, util还提供了util.isArray()、util.isRegExp(),util.isDate(),util.isError() 四个类型测试工具,以及 util.format(),til.debug() 等工具。有兴趣的读者可以访问 http://nodejs.org/api/util.html 了解详细内容
好了我们用到的工具类先介绍这里咯,太多的方法我就不一一描述了。下边我们介绍下事件驱动
事件驱动events
events 是 Node.js 最重要的模块,没有“之一”,原因是 Node.js 本身架构就是事件式的,而它提供了唯一的接口,所以堪称 Node.js 事件编程的基石。 events 模块不仅用于用户代码与 Node.js 下层事件循环的交互,还几乎被所有的模块依赖。
事件发射器
还记得我们前边讲的事件式编程吗?里边有一个EventEmitter方法还写了一个用事件event来监听我们的定义的“some_event”函数,最后通过emit推送到事件队列。想起来了吗?呵呵
如果你忘记了那我再写一次,省的你在翻到前边看了。
var events=require('events');//导入我们的events对象噢噢
var emitter = newevents.EventEmitter();//new一个发射器对象
emitter.on('someEvent',function(arg1,arg2){
console.log('listerner1',arg1,args2);
});
emitter.on('someEvent',function(arg1,arg2){
console.log('listener2',arg1,arg2);
})
emitter.emitt('someEvent','byvoid',2);
其实emitter不止这些方法噢噢他还有好多例如:
EventEmitter.on(event, listener) 为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数 listener。
EventEmitter.emit(event, [arg1], [arg2],[...]) 发射 event 事件,传递若干可选参数到事件监听器的参数表。
EventEmitter.once(event, listener) 为指定事件注册一个单次监听器,即监听器最多只会触发一次,触发后立刻解除该监听器
EventEmitter.removeListener(event,listener) 移除指定事件的某个监听器, listener 必须是该事件已经注册过的监听器。
EventEmitter.removeAllListeners([event]) 移除所有事件的所有监听器,如果指定 event,则移除指定事件的所有监听器。
看到这些是不是勾起我们一些想法吗?这跟jquery里的event对象一样啊,没错,其实eventEmiter其实就是jquery里的event对象。只不过一个在服务器端一个在客户端,呵呵为了好记住你就暂时这么记住吧。谁让jquery第一时间入驻我的思想了呢。。。
Jquery有手册node也不例外噢噢文档地址:http://nodejs.org/api/events.html。
error事件
EventEmitter 定义了一个特殊的事件 error,它包含了“错误”的语义,我们在遇到异常的时候通常会发射 error 事件。当 error 被发射时, EventEmitter 规定如果没有响应的监听器, Node.js 会把它当作异常,退出程序并打印调用栈。我们一般要为会发射 error事件的对象设置监听器,避免遇到错误后整个程序崩溃。例如:
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
运行时会显示以下错误:
node.js:201
throw e; // process.nextTick error, or'error' event on first tick
^
Error: Uncaught, unspecified 'error' event.
at EventEmitter.emit (events.js:50:15)
at Object.<anonymous>(/home/byvoid/error.js:5:9)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback(node.js:192:40)
继承EventEmitter
大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、 net、http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。为什么要这样做呢?原因有两点。首先,具有某个实体功能的对象实现事件符合语义,事件的监听和发射应该是一个对象的方法。其次 JavaScript 的对象机制是基于原型的,支持部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。
到这里我们所要讲的事件驱动就讲完了,虽然说的有点粗,但是对比起我们的jquery记起来就容易多了。希望你也懂了,如果不懂jquery那只好就死机这个node语法了,再往下看文件系统fs