stream&模块&函数&路由&global&util&fs

Stream

Stream 是一个抽象接口
四种类型

Readable - 可读操作
Writable - 可写操作
Duplex - 可读可写操作
Transform - 操作被写入数据,然后读出结果

所有Stream对象都是EventEmitter的实例
从流中读取数据

var fs = require("fs");
var data = '';

// 创建可读流
var readerStream = fs.createReadStream('input.txt');

// 设置编码为 utf8。
readerStream.setEncoding('UTF8');

// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
   data += chunk;
});

readerStream.on('end',function(){
   console.log(data);
});

readerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("程序执行完毕");

写入流

var fs = require("fs");
var data = '菜鸟教程官网地址:www.runoob.com';

// 创建一个可以写入的流,写入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');

// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');

// 标记文件末尾
writerStream.end();

// 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
    console.log("写入完成。");
});

writerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("程序执行完毕");

管道流

var fs = require("fs");

// 创建一个可读流
var readerStream = fs.createReadStream('input.txt');

// 创建一个可写流
var writerStream = fs.createWriteStream('output.txt');

// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);

console.log("程序执行完毕");

链式流
链式是通过连接输出流到另外一个流并创建多个对个流操作链的机制
链式流一般用于管道操作
压缩

var fs = require("fs");
var zlib = require('zlib');

// 压缩 input.txt 文件为 input.txt.gz
fs.createReadStream('input.txt')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('input.txt.gz'));
  
console.log("文件压缩完成。");

解压缩

var fs = require("fs");
var zlib = require('zlib');

// 解压 input.txt.gz 文件为 input.txt
fs.createReadStream('input.txt.gz')
  .pipe(zlib.createGunzip())
  .pipe(fs.createWriteStream('input.txt'));
  
console.log("文件解压完成。");

参考:
http://nodejs.cn/api/stream.html

模块系统

一个Node.js就是一个模块,可能是:JavaScript 代码、JSON、C/C++ 扩展
暴露函数

//hello.js
exports.world = function() {
  console.log('Hello World');
}

//main.js
var hello = require('./hello');
hello.world();

暴露对象

//hello.js 
function Hello() { 
	var name; 
	this.setName = function(thyName) { 
		name = thyName; 
	}; 
	this.sayHello = function() { 
		console.log('Hello ' + name); 
	}; 
}; 
module.exports = Hello;

//main.js 
var Hello = require('./hello'); 
hello = new Hello(); 
hello.setName('BYVoid'); 
hello.sayHello(); 

也可以定义exports数组

module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];

服务端模块
node中包含四种模块:原生模块和3种文件模块

requere接受的参数

http、fs、path等,原生模块
./mod或../mod,相对路径的文件模块
/pathtomodule/mod,绝对路径的文件模块
mod,非原生模块的文件模块

函数

function say(word) {
  console.log(word);
}

function execute(someFunction, value) {
  someFunction(value);
}

execute(say, "Hello");

匿名函数

function execute(someFunction, value) {
  someFunction(value);
}

execute(function(word){ console.log(word) }, "Hello");

函数传递与http服务器

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);

//同样目的
var http = require("http");

function onRequest(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);

路由

路由都包含在request对象中,作为onRequest()回调函数的第一个参数传递
解析这些参数需要url和querystring模块

          url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&hello=world
                                ---       -----
                                 |          |
                                 |          |
              querystring(string)["foo"]    |
                                            |
                         querystring(string)["hello"]
var http = require("http");
var url = require("url");

function start() {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

这样能通过url区分不同的请求

编写路由 router.js

function route(pathname) {
  console.log("About to route a request for " + pathname);
}

exports.route = route;

server.js

var http = require("http");
var url = require("url");

function start(route) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(pathname);

    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

扩展index.js

var server = require("./server");
var router = require("./router");

server.start(router.route);

全局对象

全局对象是global,所有全局变量都是它的属性

__filename  //当前脚本文件名,绝对路径
__dirname   //目录名,绝对路径
setTimeout(cb, ms)  //在指定ms毫秒后执行,cb函数

clearTimeout(t)停止创建的定时器

function printHello(){
   console.log( "Hello, World!");
}
// 两秒后执行以上函数
var t = setTimeout(printHello, 2000);

// 清除定时器
clearTimeout(t);

setInterval(cb, ms)不停执行,clearInterval(t)清除

function printHello(){
   console.log( "Hello, World!");
}
// 两秒后执行以上函数
setInterval(printHello, 2000);

console对象的方法

console.log([data][, ...])
console.info([data][, ...])
console.error([data][, ...])
console.warn([data][, ...])
console.dir(obj[, options])
console.time(label)
console.timeEnd(label)
console.trace(message[, ...])
console.assert(value[, message][, ...])
console.log('byvoid%diovyb', 1991)
console.error():与console.log() 用法相同,只是向标准错误流输出
console.trace():向标准错误流输出当前的调用栈

main.js

console.info("程序开始执行:");

var counter = 10;
console.log("计数: %d", counter);

console.time("获取数据");
//
// 执行一些代码
// 
console.timeEnd('获取数据');

console.info("程序执行完毕。")

process
参考:http://nodejs.cn/api/process.html
全局变量,描述Node进程状态,提供一个与操作系统交互的接口

exit                //进程准备退出时触发
beforeExit          //node清空事件循环,没有其他安排时触发这个事件
uncaughtException   //一个异常冒泡到事件循环
Signal              //接受posix信号

创建文件main.js

process.on('exit', function(code) {

  // 以下代码永远不会执行
  setTimeout(function() {
    console.log("该代码不会执行");
  }, 0);
  
  console.log('退出码为:', code);
});
console.log("程序执行结束");

退出状态码

1	Uncaught Fatal Exception
    有未捕获异常,并且没有被域或 uncaughtException 处理函数处理。
2	Unused
    保留
3	Internal JavaScript Parse Error
    JavaScript的源码启动 Node 进程时引起解析错误。非常罕见,仅会在开发 Node 时才会有。
4	Internal JavaScript Evaluation Failure
    JavaScript 的源码启动 Node 进程,评估时返回函数失败。非常罕见,仅会在开发 Node 时才会有。
5	Fatal Error
    V8 里致命的不可恢复的错误。通常会打印到 stderr ,内容为: FATAL ERROR
6	Non-function Internal Exception Handler
    未捕获异常,内部异常处理函数不知为何设置为on-function,并且不能被调用。
7	Internal Exception Handler Run-Time Failure
    未捕获的异常, 并且异常处理函数处理时自己抛出了异常。例如,如果 process.on('uncaughtException') 或 domain.on('error') 抛出了异常。
8	Unused
    保留
9	Invalid Argument
    可能是给了未知的参数,或者给的参数没有值。
10	Internal JavaScript Run-Time Failure
    JavaScript的源码启动 Node 进程时抛出错误,非常罕见,仅会在开发 Node 时才会有。
12	Invalid Debug Argument 
    设置了参数--debug 和/或 --debug-brk,但是选择了错误端口。
>128	Signal Exits
    如果 Node 接收到致命信号,比如SIGKILL 或 SIGHUP,那么退出代码就是128 加信号代码。这是标准的 Unix 做法,退出信号代码放在高位。

Process属性

stdout
stderr
stdin
argv            //数组,第一个node,第二个文件名,其他参数
execPath
execArgv
env
exitCode
version
versions
config
pid
title
arch
platform
mainModule

参考:http://www.runoob.com/nodejs/nodejs-global-object.html
main.js

// 输出到终端
process.stdout.write("Hello World!" + "\n");

// 通过参数读取
process.argv.forEach(function(val, index, array) {
   console.log(index + ': ' + val);
});

// 获取执行路局
console.log(process.execPath);

// 平台信息
console.log(process.platform);

方法

1	abort()
    这将导致 node 触发 abort 事件。会让 node 退出并生成一个核心文件。
2	chdir(directory)
    改变当前工作进程的目录,如果操作失败抛出异常。
3	cwd()
    返回当前进程的工作目录
4	exit([code])
    使用指定的 code 结束进程。如果忽略,将会使用 code 0。
5	getgid()
    获取进程的群组标识(参见 getgid(2))。获取到得时群组的数字 id,而不是名字。
    注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
6	setgid(id)
    设置进程的群组标识(参见 setgid(2))。可以接收数字 ID 或者群组名。如果指定了群组名,会阻塞等待解析为数字 ID 。
    注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
7	getuid()
    获取进程的用户标识(参见 getuid(2))。这是数字的用户 id,不是用户名。
    注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
8	setuid(id)
    设置进程的用户标识(参见setuid(2))。接收数字 ID或字符串名字。果指定了群组名,会阻塞等待解析为数字 ID 。
    注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
9	getgroups()
    返回进程的群组 iD 数组。POSIX 系统没有保证一定有,但是 node.js 保证有。
    注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
10	setgroups(groups)
    设置进程的群组 ID。这是授权操作,所有你需要有 root 权限,或者有 CAP_SETGID 能力。
    注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
11	initgroups(user, extra_group)
    读取 /etc/group ,并初始化群组访问列表,使用成员所在的所有群组。这是授权操作,所有你需要有 root 权限,或者有 CAP_SETGID 能力。
    注意:这个函数仅在 POSIX 平台上可用(例如,非Windows 和 Android)。
12	kill(pid[, signal])
    发送信号给进程. pid 是进程id,并且 signal 是发送的信号的字符串描述。信号名是字符串,比如 'SIGINT' 或 'SIGHUP'。如果忽略,信号会是 'SIGTERM'。
13	memoryUsage()
    返回一个对象,描述了 Node 进程所用的内存状况,单位为字节。
14	nextTick(callback)
    一旦当前事件循环结束,调用回到函数。
15	umask([mask])
    设置或读取进程文件的掩码。子进程从父进程继承掩码。如果mask 参数有效,返回旧的掩码。否则,返回当前掩码。
16	uptime()
    返回 Node 已经运行的秒数。
17	hrtime()
    返回当前进程的高分辨时间,形式为 [seconds, nanoseconds]数组。它是相对于过去的任意事件。该值与日期无关,因此不受时钟漂移的影响。主要用途是可以通过精确的时间间隔,来衡量程序的性能。
    你可以将之前的结果传递给当前的 process.hrtime() ,会返回两者间的时间差,用来基准和测量时间间隔。

例子

// 输出当前目录
console.log('当前目录: ' + process.cwd());

// 输出当前版本
console.log('当前版本: ' + process.version);

// 输出内存使用情况
console.log(process.memoryUsage());

常用工具

util提供常用的函数集合,弥补js核心过于精简的不足
util.inherits(constructor, superConstructor)实现对象间原型继承
只能继承原形中的内容

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(); 
//objSub.sayHello(); 
console.log(objSub); 

基础对象Base 和一个继承自Base的Sub
Sub 仅仅继承了Base 在原型中定义的函数,而构造函数内部创造的 base 属 性和 sayHello 函数都没有被 Sub 继承
util.inspect(object,[showHidden],[depth],[colors])
将任意对象转换 为字符串的方法
showHidden 是一个可选参数,如果值为 true,将会输出更多隐藏信息。
depth 表示最大递归的层数,如果对象很复杂,你可以指定层数以控制输出信息的多 少。如果不指定depth,默认会递归2层
指定为 null 表示将不限递归层数完整遍历对象。 如果color 值为 true,输出格式将会以ANSI 颜色编码,通常用于在终端显示更漂亮 的效果。

var util = require('util'); 
function Person() { 
	this.name = 'byvoid'; 
	this.toString = function() { 
	return this.name; 
	}; 
} 
var obj = new Person(); 
console.log(util.inspect(obj)); 
console.log(util.inspect(obj, true)); 

util.isArray(object),如果object是个数组返回true,否则返回false

var util = require('util');

util.isArray([])
  // true
util.isArray(new Array)
  // true
util.isArray({})
  // false

util.isRegExp(object),"object" 是一个正则表达式返回true,否则返回false

var util = require('util');

util.isRegExp(/some regexp/)
  // true
util.isRegExp(new RegExp('another regexp'))
  // true
util.isRegExp({})
  // false

util.isDate(object)
util.isError(object)
更多:
https://nodejs.org/api/util.html

文件系统

fs模块所有的方法均有异步和同步的方法
参考:
https://nodejs.org/api/fs.html
http://www.runoob.com/nodejs/nodejs-fs.html

posted @ 2017-03-21 13:04  zhangshihai1232  阅读(172)  评论(0)    收藏  举报