编辑推荐: |
本文来自于网络
介绍了CommonJS规范,全局对象,内置模块,Node.js实现HTTP服务器程序,Node.js实现文件服务器等知识。 |
|
CommonJS规范
每一个js文件都是一个模块,js文件的名字就是模块的名字。每个模块内部使用的变量名和函数名互不冲突。
一个模块想要对外暴露变量(函数也是变量),可以用module.exports = variable,还可以exports.variable=variable;如果要输出一个键值对象{},可以利用exports这个已存在的空对象{},并继续在上面添加新的键值;如果要输出一个函数或数组,必须直接对module.exports对象赋值。
一个模块要引用其他模块暴露的变量,用var ref = require('module_name');就拿到了引用模块的变量。在引用模块时要把相对路径写对,直接写模块名会依次在内置模块、全局模块和当前模块下查找。
全局对象
node.js的全局对象global相当于浏览器环境中的全局对象window。
根据全局对象判断JavaScript的执行环境;
if(typeof(window)==='undefined'){
console.log('node.js');
}else{
console.log('browser');
} |
node.js的process对象
process=global.process,代表当前Node.js进程;
process.nextTick(function(){});nextTick中的函数不会立刻执行,而是要等到下一次事件循环;
process.on('exit',function(){});在程序即将退出时执行该回调函数。
内置模块
fs模块
文件系统模块,负责读写文件。fs模块同时提供了异步和同步的方法。
异步方法
因为JavaScript的单线程模型,执行IO操作时,JavaScript代码无需等待,而是传入回调函数后,继续执行后续JavaScript代码。
$.getJSON ('http://example.com
/ajax',function(data ) {
console.log ('IO结果返回执行...');
});
console.log ('不等待IO结果直接执行后续代码...'); |
同步方法
同步方法:同步的IO操作则需要等待函数返回。
var data=getJSONSync
('http://example.com/ajax'); |
同步操作的好处是代码简单,缺点是程序将等待IO操作,在等待时间内,无法响应其它任何事件。而异步读取不用等待IO操作,但代码较麻烦。
异步与同步
由于Node环境执行的JavaScript代码是服务器端代码,所以,绝大部分需要在服务器运行期反复执行业务逻辑的代码,必须使用异步代码,否则,同步代码在执行时期,服务器将停止响应,因为JavaScript只有一个执行线程。
服务器启动时如果需要读取配置文件,或者结束时需要写入到状态文件时,可以使用同步代码,因为这些代码只在启动和结束时执行一次,不影响服务器正常运行时的异步执行。
异步读文件
'use strict';
var fs=require('fs');
fs.readFile('sample.txt','utf-8',function (err
,data ) {
if(err){
console.log (err);
}else{
console.log (data);
}
});
console.log ('start process'); |
sample.txt文件必须在当前目录,utf-8为文件的编码;
node.js标准的回调函数,第一个参数代表错误信息,第二个参数代表结果;
当读取二进制文件时,不传入文件编码时,回调函数的data参数将返回一个Buffer对象。在Node.js中,Buffer对象就是一个包含零个或任意个字节的数(注意和Array不同)。
Buffer对象与String之间的转换:
Buffer->
String:var text=data.toString ('utf-8');
String-> Buffer:var buf=Buffer.from (text,'utf-8
'); |
同步读文件
'use strict';
var fs=require('fs');
try{
var data=fs.readFileSync ('sample.txt','utf-8');
console .log (data);
}catch (err){
console.log (err);
}
console.log ('start'); |
异步写文件
'use strict'
var fs=require('fs');
var data='write data into file';
fs.writeFile ('sample.txt',data,function (err){
if (err){
console.log(err);
}else{
console.log('done!');
}
}); |
writeFile()的参数依次为文件名、数据和回调函数。如果传入的数据是String,默认按UTF-8编码写入文本文件,如果传入的参数是Buffer,则写入的是二进制文件。回调函数由于只关心成功与否,因此只需要一个err参数。
同步写文件
'use strict';
var fs=require('fs');
var data='write date into file';
fs.writeFileSync ('output.txt',data); |
获取文件大小、创建时间等信息
fs.stat()返回一个Stat对象,能告诉我们文件或目录的详细信息。
//异步
'use strict';
var fs=require('fs');
fs.stat('sample.txt',function(err,stat){
if(err){
console.log(err);
}else{
console.log('isFile:'+stat.isFile());
console.log('isDirectory:'+stat.isDirectory());
if(stat.isFile()){
console.log('size:'+stat.size);
console.log('birth time:'+stat.birthtime);
console.log('modified time:'+stat.mtime);
}
}
});
//同步
'use strict';
var fs=require('fs');
try{
var stat=fs.statSync ('sample.txt');
console.log ('isFile:'+stat.isFile());
console.log ('isDirectory:'+stat.isDirectory());
if(stat.isFile( )){
console. log ('size:'+stat.size);
console.log ('birth time:'+stat.birthtime);
console.log ('modified time:'+stat.mtime);
}
}catch(err){
console.log (err);
} |
流读写文件
所有能读取数据的流都继承自stream.Readable;所有能写入数据的流都继承自stream.Writable;
//读操作
'use strict';
var fs = require('fs');
var rs = fs.createReadStream ('sample.txt', 'utf-8'
)
rs.on('data', function (chunk) {//data事件表示流的数据已经可以读取。
console.log('DATA:');
console.log(chunk);
});
rs.on('end', function () {//end事件表示这个流已经到了末尾,没有数据可读。
console.log('END');
});
rs.on('error', function (err) { //error表示事件出错。
console.log ('ERROR: ' + err);
});
//写操作
var ws=fs.createWriteStream ('sample.txt','utf-8');
ws.write ('write data into file with stream');
ws.end; |
pipe
一个Readable流和一个Writable流串起来后,所有数据自动从Readable流进入Writeable流,这种操作叫pipe。
默认情况下,当Readable流的数据读取完毕,end事件触发后,将自动关闭Writable流。如果我们不希望自动关闭Writable流,需要传入参数
readable.pipe(writable,{end:false});
Node.js实现HTTP服务器程序
处理TCP连接,解析HTTP都由http模块完成了,HTTP请求和HTTP响应都分别封装在http模块中的request对象和response对象中。
//简单的HTTP服务程序
'use strict';
var http=require('http');
var server=http.createServer (function (request
,response ){
console.log (request.method +":"+request.url);
response.writeHead(200,{'Content-Type ':' text/
html ' });
response.end ('<h1>hello world</h1>');
} );
server.listen (8080);
console.log ('Server is running at http: // 127.0.
0 . 1 : 8080/') ; |
Node.js实现文件服务器
解析URL需要用到Node.js提供的url模块,通过parse()将一个字符串解析为一个Url对象;
处理本地文件目录需要使用Node.js提供的path模块,使用path模块可以正确处理操作系统相关的文件路径;
//简单的文件服务器
'use strict';
var
fs=require ('fs'),
url=require ('url'),
path=require ('path'),
http=require ('http');
// 从命令行参数获取root目录,默认是当前目录
var root = path.resolve (process.argv[2] || '.');
console.log (process.argv[2]);
console.log ('Static root dir: ' + root);
var server=http. createServer (function(request
, response ){
var pathname = url.parse (request.url).pathname;
var filepath = path.join (root, pathname);
fs.stat(filepath, function (err, stats) {
if (!err && stats.isFile()) {
console .log ('200 ' + request.url);
response.writeHead (200,{'Content-Type':' text/html
; charset = utf-8'});
//response.write ('<meta charset="utf-8"/>
');
fs . createReadStream (filepath).pipe(response);//由于
response对象本身是一个Writable Stream,直接用pipe () 方法就实现了自动读取文件内容并输出到HTTP响应
} else {
console. log ('404 ' + request.url);
response.writeHead (404);
response.end ('404 Not Found');
}
});
});
server.listen (8080);
console.log ('Server is running at http://127.0.0.1:8080/'); |
node.js的加密模块crypto
crypto模块的目的是为了提供通用的加密和哈希算法,Nodejs用C/C++实现这些算法后,通过cypto这个模块暴露为JavaScript接口。
MD5和SHA1
const crypto=require
('crypto');
const hash=crypto.createHash ('md5');
// 098f6bcd4621d373cade4e832627b4f6
// const hash=crypto.createHash('sha1'); //a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
hash.update('test'); //update () 方法默认字符串编码为UTF-8,也可以传入Buffer
console.log(hash.digest ('hex')); //以十六进制的方式输出
|
|