《Node.js开发指南》知识整理
Node.js简介
Node是⼀个可以让JavaScript运⾏在服务器端的平台,抛弃了传统平台依靠多线程来实现⾼并发的设计思路,⽽采⽤单线程、异步式I/O、事件驱动式的程序设计模型。
安装和配置Node.js
安装配置简单,⽆需多说。
Node.js快速⼊门
异步式I/O与事件式编程
回调函数
⽤异步的⽅式读取⼀个⽂本内容为“test content”的⽂件,代码如下:
var fs = require("fs");
console.log(data);
});
console.log("end");
运⾏的结果:
end
test content
使⽤同步的⽅式读取⽂件:
var fs = require("fs");
console.adFileSync("", "utf-8"));
console.log("end");
运⾏结果:
test content
end
同步的⽅式是阻塞线程等待⽂件读取完毕后,将⽂件内容输出,然后才继续执⾏下⼀步代码,因此控制台先打印“test content”,然后再打
印“end”。
⽽异步式I/O是通过回调函数来实现的,通过将控制台输出⽂件内容的函数作为参数传给fs.readFile函数,fs.readFile调⽤时只是将异步式I/O 请求发送给操作系统,然后⽴即返回并执⾏后⾯的语句,当fs接收到I/O请求完成的事件时,才会调⽤回调函数。因此我们先看到“end”,再看到“”的内容。
事件
Node.js所有的异步I/O操作在完成时都会发送⼀个事件到事件队列。事件由EventEmitter提供,前⾯提到的fs.readFile的回调函数就是通过EventEmitter来实现。
模块和包
Node提供了require函数来调⽤其他模块。node中的模块和包并没有本质的区别,包可以理解为某个功能模块的集合。
什么是模块
模块是node应⽤程序的基本组成部分,⽂件和模块是⼀⼀对应的。⼀个node.js⽂件就是⼀个模块,这个⽂件可能是JavaScript代码、JSON 或者编译过的C/C++扩展。
创建及加载模块
node提供了exports和require两个对象,其中exports是模块的公开接⼝,require⽤于从外部获取⼀个模块的接⼝。
新建⼀个myModule.js⽂件,输⼊如下代码:
var text;
function setText(myText){
text = myText;
}
function printText(){
console.log(text);
}
exports.setText = setText;
exports.printText = printText;
再新建⼀个test.js⽂件:
var myModule = require("./myModule");
myModule.setText("Hello world!");
myModule.printText();
运⾏test.js,结果为:
Hello world!
单次加载
模块的调⽤与创建⼀个对象不同,require不会重复加载模块。
修改test.js:
var myModule1 = require("./myModule");
myModule1.setText("Hello world!");
var myModule2 = require("./myModule");
myModule2.setText("Hi baby!");
myModule1.printText();
myModule2.printText();
运⾏结果:
Hi bayby!
Hi bayby!
这是因为模块不会重复加载,myModule1和myModule2指向的都是同⼀个实例,因此myModule1的text值就被myModule2覆盖了。创建包
包是模块基础上更深⼀步的抽象,类似于C/C++的函数库或者java/的类库。
node包是⼀个⽬录,其中包括⼀个JSON格式的包说明⽂件package.json。node对包的要求并不严格,但还是建议制作包时遵循CommonJS规范。
建⽴⼀个名为mypackage的⽂件夹,在⽂件夹中新建index.js:
exports.hello = function(){
console.log("Hello world");
};
然后在mypackage之外建⽴test.js:
var mypackage = require("./mypackage");
mypackage.hello();
这就是⼀个简单的包了,通过定制package.json,我们可以创建更复杂的包。
定制package.json:
1. 在mypackage⽂件夹下创建⼀个package.json⽂件和⼀个lib⼦⽂件夹。
2. 将index.js重命名为interface.js并放⼊lib⽂件夹。
3. 打开package.json并输⼊如下json⽂本:
{
"main": "./lib/interface.js"
}
运⾏test.js,依然可以看到控制台输出“Hello world”。
node调⽤某个包时,会⾸先检查package.json⽂件的main字段,将其作为包的接⼝模块,如果package.json或main字段不存在,就会去寻index.js或de作为包的接⼝。
node.js包管理器
本地模式和全局模式
也可以使⽤全局安装,它会将包安装在系统⽬录:
“npm [install/i] -g [package_name]”
本地模式可以直接通过require使⽤,但是不会注册环境变量。
全局模式不能直接通过require使⽤,但是它会注册环境变量。
npm link
通过npm link命令可以在本地包和全局包之间创建符号链接,使全局包可以通过require使⽤,例如要require全局模式安装的express,可以在⼯程⽬录下运⾏:
npm link express
使⽤npm link命令还可以将本地包链接到全局,但是npm link命令不⽀持windows。
调试
命令⾏调试
例如要调试test.js,则在命令⾏中输⼊:
node debug test.js
以下为基本的调试命令:
run:执⾏脚本,在第⼀⾏暂停
restart:重新执⾏脚本
cont, c:继续执⾏,直到遇到下⼀个断点
next, n:单步执⾏
step, s:单步执⾏并进⼊函数
out, o:从函数中步出
setBreakpoint(), sb():在当前⾏设置断点
setBreakpoint(‘f()’), sb(...):在函数f的第⼀⾏设置断点
setBreakpoint(‘script.js’, 20), sb(...):在 script.js 的第20⾏设置断点
clearBreakpoint, cb(...):清除所有断点
backtrace, bt:显⽰当前的调⽤栈
list(5):显⽰当前执⾏到的前后5⾏代码
watch(expr):把表达式 expr 加⼊监视列表
unwatch(expr):把表达式 expr 从监视列表移除
watchers:显⽰监视列表中所有的表达式和值
repl:在当前上下⽂打开即时求值环境
kill:终⽌当前执⾏的脚本
scripts:显⽰当前已加载的所有脚本
version:显⽰ V8 的版本
远程调试
使⽤以下语句之⼀可以打开调试服务器:
node --debug[=port] test.js //脚本正常执⾏,调试客户端可以连接到调试服务器。
node --debug-brk[=port] test.js //脚本暂停执⾏等待客户端连接。
如不指定端⼝,则默认为5858。
客户端:
node debug 127.0.0.1:5858
node-inspector
安装node-inspector:
npm install -g node-inspector
在终端连接调试服务器:
node --debug-brk=5858 test.js
启动node-inspector:
node-inspector
Node.js核⼼模块
全局对象
在浏览器javascript中,通常window就是全局对象,⽽在node中全局对象是global,它是全局变量的宿主,全局变量是它的属性。process
⽤于描述当前node进程状态,提供⼀个与操作系统的简单接⼝。
常⽤成员⽅法
process.argv:
命令⾏参数数组,第⼀个元素是node,第⼆个元素是脚本⽂件名,从第三个元素开始每个元素都是⼀个运⾏参数。
process.stdout:
标准输出流,通常我们使⽤的console.log()向标准输出打印字符,⽽process.stdout.write()函数提供更底层的接⼝。
process.stdin:
标准输⼊流。
其他成员⽅法
process.platform; process.pid; Path; Usage()
console
⽤于提供控制台标准输出。
常⽤成员⽅法
console.log():
向标准流打印字符并以换⾏符结束,可以使⽤类似C语⾔printf()命令的格式输出。
<():
向标准错误流输出。
向标准错误流输出当前的调⽤栈。
常⽤⼯具util
⽤于提供常⽤函数集合。
util.inherits(constructor, superConstructor)
实现对象间原型继承的函数。
js脚本编程入门
var util = require("util");
function Base() {
this.name = "base";
this.base = 1991;
this.sayHello = function(){
console.log("hello " + this.name);
};
}
Base.prototype.showName = function(){
console.log(this.name);
};
function Sub(){
this.name = "sub";
}
util.inherits(Sub, Base);
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
console.log(objSub);
输出结果:
base
Hello base
{ name: 'base', base: 1991, sayHello: [Function] }
sub
{ name: 'sub' }
Sub只继承了Base在原型中定义的函数,⽽函数内部的base属性和sayHello函数都没有被继承。⽽且,在原型中定义的属性不会被console.log()作为对象的属性输出。
util.inspect(object, [showHidden], [depth], [colors])
将任意对象转换为字符串,通常⽤于调试和错误输出。
object:要转换的对象。
showHidden:如果为true,将会输出更多隐藏信息。
depth:表⽰最⼤递归的层数,默认会递归2层,指定为null表⽰不限制最⼤递归数完整遍历对象。
color:如果为true,输出格式将会以ANSI颜⾊编码。
util.inspect不会简单的直接将对象转换成字符成,即便是对象定义了toString⽅法也不会调⽤。
其他函数
util.isArray(); util.isRegExp(); util.isDate(); util.isError(); util.format(); util.debug();
事件驱动events
events是node最重要的模块,因为node本⾝架构就是事件式的,⽽它提供了唯⼀的接⼝。
事件发射器
events.EventEmitter的核⼼就是事件发射与事件功能的封装。
var events = require("events");
var emitter = new events.EventEmitter();
<("testEvent", function( arg1, arg2){
console.log(arg1, arg2);
});
以上为EventEmitter基本⽤法。
常⽤API:
<(event, listener):
为指定事件注册⼀个,接收⼀个字符串event和⼀个回调函数listener。
发射event事件。
<(event, listener):
为指定事件注册⼀个单次,触发后⽴刻解除。
移除指定事件的某个。
移除所有事件的所有,如果指定event,则移除指定事件的所有。
error事件
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论