Node.js 精华一页纸

Node.js 本质上是一个运行平台,提供提供文件/网络等系统资源,从而使js语言有了操纵服务端的能力。应该说Node.js的出现有 划时代的作用,以前只把js定位为前端语言,有了Node.js 后 js变成了全栈语言。

除了Node.js以外,熟悉java的同志可以发现 java有相应的js执行引擎 rhino / nashron,通过java搭建平台后,可以达到Node.js 的功效。

1、典型例子


var http = require('http');
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8888);

// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');

步骤
I、引入XXX模块,这里 引入的是 Http模块
II、创建一个 node 的对象
III、通过node对象进行处理

2、事件循环


因为系统资源基本都是需要操作IO的,比如文件系统,网络等等。这就需要涉及IO操作的几种方式:同步 or 异步;阻塞 or 非阻塞 - 具体可以参照本博《java io 精华一页纸》
Node.js 因为是单进程单线程的,要处理这些IO,就只能采用异步的方式,即通过事件和回调函数来实现事件的处理

这个非常类似 NIO 的并发机制,其实,执行 事件触发后的调用,如果不使用多线程或者队列,还是有阻塞的

// I、引入 events 模块
var events = require('events');
// II、创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// III、创建事件处理程序
var connectHandler = function connected() {
console.log('connect finish');
}
// IV、绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
// V、触发 connection 事件
eventEmitter.emit('connection');
console.log("exit");

一般情况下,fs\net 这些模块都继承Events,很少直接使用 event 对象;

特殊事件:error 类,系统发现 error类的事件,如果未定义处理方法,则node进程退出。

3、组件化/模块化


作为框架提供组件化/模块化几乎是一个标准配置;NodeJS 在模块方面,主要有两部分,一是 导出方法;另一个是导出对象
对象.js
function ObjectExport(name){
this.name = name;

this.showName = function(){
console.log(name);
}
}

module.exports = ObjectExport

这个时候就可以像系统自带对象一样引用这个对象
var obj = require("./useExport");
var aa = new obj("aa");
aa.showName();

4、常见系统对象


文件系统 fs
-- 和java读写文件类似
打开文件 -- fs.open(path,flag,mode,callback);
读写文件 -- fs.read | fs.write
关闭文件 -- fs.close
其他删除,目录操作等等有很多

fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("success open file");
console.log("ready read file");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}

// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}

// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("close success");
});
});
});

网络操作 tcp/ip
var net = require('net');
var server = net.createServer(function(connection) {
console.log('client connected');
connection.on('end', function() {
console.log('客户端关闭连接');
});
connection.write('Hello World!\r\n');
connection.pipe(connection);
});
server.listen(3000, function() {
console.log('server is listening');
});

var net = require('net');
var client = net.connect(3000,'localhost', function() {
console.log('连接到服务器!');
});
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
client.on('end', function() {
console.log('断开与服务器的连接');
});

操作系统 - os
可以获取操作系统信息

dns

域 - domain

路径操作 - path

...

5、IO流


既然都是IO操作为主,一定需要处理系统流;JavaScript只有操作字符型的数据,没有二进制的数据,Node 提供了流处理类
I、Buffer类
a、定义buff (用法类似arraylist,指定容量|指定数组|字符串等)
var buf = new Buffer("aaabbbcc","utf-8");
b、读写
buf.write("12345","utf-8");
buf.toString("utf-8",0,5)
c、其他操作
转换json buf.toJSON(buf);
类似集合操作 比较 compare | 合并 concat | 截取 slice

II、Stream流
Stream 是一个抽象接口(类似于Java的 InputStream 这种),Node.js中很多涉及IO操作的都实现了该接口,比如 http请求的 request
四种流类型 Readable - 可读 类似InputStream | Writable - 可写 类似OutputStream | Duplex - 可读可写 类似RandomAccessFile | Transform - 写入数据然后读
流常见的事件有 data - 数据就绪 | end - 流结束 | error - 读取流错误 | finish - 所有数据已写入

a、基本流

var fs = require("fs");
var data = '';
var readerStream = fs.createReadStream('streamfile.js');
readerStream.setEncoding('UTF8');
readerStream.on('data', function(chunk) {
data += chunk;
});

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

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

var writeStream = fs.createWriteStream("out.txt");
writeStream.write(data);
writeStream.end();
writeStream.on('finish', function(){
console.log("Write Finish");
});

console.log("Process Exit");

b、管道 -- 类似于 Java的pipe
readerStream.pipe(writerStream)
-- 只需要把读流和写流联系在一起即可。

可以把 管道不断链接起来,实现链式 流操作

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

// 读取 streamlink.js ,然后压缩,最后再写入新的压缩文件
fs.createReadStream('streamlink.js')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('streamlink.js.gz'));

console.log("finish");

6、多进程


nodejs 是单进程 单线程 (用户处理是单线程,但nodejs 肯定有一个事件线程在轮询) 模式运行,通过事件驱动来处理并发;这在某些场合下并不能满足,所以NodeJS提供了多进程的用法。

创建子进程的三种方式(每个子进程都携带 child.stdin child.stdout child.stderr 三个流) -- 这个做法和H5的多线程理念非常类似

exec -- 类似 Java 的 Rumtime.exec, 启动一个子进程执行命令
spawn -- 使用命令行参数创建新的进程
fork -- 类似于 C 的fork 一个子进程出来

const fs = require('fs');
const child_process = require('child_process');

for(var i=0; i<3; i++) {
var workerProcess = child_process.exec('node support.js '+i,
function (error, stdout, stderr) {
if (error) {
console.log(error.stack);
console.log('Error code: '+error.code);
console.log('Signal received: '+error.signal);
}
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
});

workerProcess.on('exit', function (code) {
console.log('子进程已退出,退出码 '+code);
});
}

7、其他知识


REPL 交互式解释器 -- 命令终端下执行nodejs代码
系统自带全局对象和属性 -- 这点和浏览器对象差不多,常见的 console / process, __filename / setTimeout
工具库 util -- 提供了大量的公共方法
NPM -- 包管理工具
Express -- Web框架
...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值