原生Node.js的一些重要内容总结
2017-12-30 本文已影响27人
Yytg
原生Node.js的一些重要内容总结
1.数据交互
2.流(stream)
3.压缩(zlib)
4.管道操作(pipe)
5.接口管理(Router)
6.Cluster(,集群(多进程)
7.crypto(加密)
1.数据交互
常见的三种数据交互方式:
1.GET方式:
js:
const http = require('http');
const url = require('url');
http.createServer((req,res)=>{
let {pathname,query} = url.parse(req.url,true);
console.log('接收了get请求',pathname,query);
res.end();
}).listen(8080);
html:
<form action="http://localhost:8080" method="get">
用户:<input type="text" name='user'/><br>
密码:<input type="password" name="pass"><br>
<input type="submit" name="sub" value="提交">
</form>
2.POST(urlencoded)
js:
// node.js数据交互
const http = require('http');
const url = require('url');
const querystring = require('querystring');
let server = http.createServer((req,res)=>{
// post请求 urlencoded
let aBuffer = [];
req.on('data',data=>{
aBuffer.push(data);
});
req.on('end',()=>{
let data = Buffer.concat(aBuffer);
let datas = querystring.parse(data.toString());
console.log(datas);
})
});
server.listen(8080,()=>{
console.log('this server running 8080 port');
});
html:
<form action="http://localhost:8080" method="post" enctype="application/x-www-form-urlencoded">
用户:<input type="text" name='user'/><br>
密码:<input type="password" name="pass"><br>
<input type="submit" name="sub" value="提交">
3.POST(form-data)
html:
<form action="http://localhost:8080/login" method="post" enctype="multipart/form-data">
用户: <input type="text" name="user" /><br>
密码: <input type="password" name="pass"><br>
<input type="file" name="f1" value="选择"><br>
<input type="file" name="f2" value="选择"><br>
<input type="file" name="f3" value="选择"><br>
<input type="submit" value="注册">
这种方式得到的数据要进行判断处理才可以,因为还涉及文件的上传。
而得到的数据是Buffer,它是二进制数据。所以要处理二进制数据。得到的Buffer格式为:
------WebKitFormBoundaryq9dAWVB72Rj30S9c
Content-Disposition: form-data; name="user"
blue
------WebKitFormBoundaryq9dAWVB72Rj30S9c
Content-Disposition: form-data; name="pass"
123456
------WebKitFormBoundaryq9dAWVB72Rj30S9c
Content-Disposition: form-data; name="f1"; filename="1.txt"
Content-Type: text/plain
aaa
bbb
ccc
------WebKitFormBoundaryq9dAWVB72Rj30S9c--
处理代码如下:
// node.js数据交互
const http = require('http');
const url = require('url');
const querystring = require('querystring');
const common = require('./libs/common');
const fs = require('fs');
const uuid = require('uuid/v4');
const path = require('path');
let server = http.createServer((req,res)=>{
let aBuffer = [];
req.on('data',data=>{
aBuffer.push(data);
});
req.on('end',()=>{
let data = Buffer.concat(aBuffer);
if(req.headers['content-type'].startsWith('multipart/form-data')){ //file
let post = {};
let files = {};
// 提取分隔符
const boundary = '--'+req.headers['content-type'].split('; ')[1].split('=')[1];
//console.log(boundary);
// 分割符切分
let arr = data.split(boundary);
//console.log(arr.map(item=>item.toString()));
// 扔掉头尾(<>、<--\r\n>)
arr.shift();
arr.pop();
// 每一项处理
// 每一项的头尾扔掉(\r\n....\r\n)
arr = arr.map(item=>item.slice(2,item.length-2));
// 找到第一个'\r\n\r\n',切开,一半信息,一半数据
arr.forEach(item=>{
let n = item.indexOf('\r\n\r\n');
let info = item.slice(0,n);
let data = item.slice(n+4);
info = info.toString();
// console.log(infor);
let total = 0;
let complete = 0;
if(info.indexOf('\r\n')==-1){ //只有一行信息 普通数据
let key = common.parseInfo(info).name;
info = info.toString();
post[key] = data;
}else{ // 两行数据 文件
total++;
let json = common.parseInfo(info);
let key = json.name;
let filename = json.filename;
console.log(json);
console.log(filename);
let type = json['content-type'];
let filepath = `upload/${uuid().replace(/\-/g,'')}${path.extname(filename)}`;
files[key] = {filename,type,filepath};
fs.writeFile(filepath,data,err=>{
if(err){
console.log('文件写入失败');
}else{
console.log('写入成功');
complete++;
console.log(post,files);
}
});
}
})
}else{ // urlencoded
let post = querystring.parse(data.toString());
console.log(post);
}
})
});
server.listen(8080,()=>{
console.log('this server running 8080 port');
});
-------------------------------------------------------------------------------------------------
common.js:
Buffer.prototype.split = Buffer.prototype.split||function(spliter){
let b1 = this;
let result = [];
let n;
while((n=b1.indexOf(spliter))!=-1){
let res1 = b1.slice(0,n);
let res2 = b1.slice(n+spliter.length);
result.push(res1);
b1 = res2;
}
result.push(b1);
return result;
}
exports.parseInfo = function(str){
let arr = str.split('; ');
let arr2 = [];
arr.forEach(item=>{
let a = item.split('\r\n');
arr2 = arr2.concat(a);
});
let json = {};
arr2.forEach(s=>{
let [key,val] = s.split('=');
if(!val){
json[key] = val;
}else{
json[key] = val.substring(1,val.length-1);
}
});
return json;
}
2.流(stream)和管道操作
真正的数据传输肯定要转为流的方式进行传输,它可以减少内存占用、增强系统性能(利用率高)。
流的传输方式是读一块,发一块。
分为读取流,写入流,读写流(压缩,加密就是读取流)。
读取流:request,fs.createReadStream.
写入流:response,fs.createWriteStream.
onst fs = require('fs');
const zlib = require('zlib');
let gz = zlib.createGzip();
let rs = fs.createReadStream('www/1.html'); // 创建读取流
let ws = fs.createWriteStream('www/2.html.gz'); // 创建写入流
rs.pipe(gz).pipe(ws); // 管道操作
4.压缩(zlib)
数据必须进行压缩处理,再进行传输。在Node.js中它是配合流和管道一起使用的。
5.接口管理(Router)
创建EventEmitter对象
:EventEmitter 可以模拟一个事件队列(相应的监听与触发)
const Event = require('events').EventEmitter; // EventEmitter 模拟一个事件队列
let ev = new Event();
// 监听
ev.on('clearboy',function(a,b,c,d){
console.log('收到1个事件',a,b,c,d);
})
ev.on('clearboy',function(a,b,c,d){
console.log('收到2个事件',a,b,c,d);
})
// 触发
let a = ev.emit('clearboy',1,2,3,4);
console.log(a) // true
既有监听又有触发,则返回的结果为a为true,否则为false,以此判断是接口还是普通的文件读取.
const http = require('http');
const url = require('url');
const router = require('./libs/router');
const user = require('./routers/user');
const fs = require('fs');
const zlib = require('zlib');
http.createServer((req,res)=>{
let { pathname, query } = url.parse(req.url,true);
req.query = query;
res.send = function(data){
if(!(data instanceof Buffer) && typeof data!='string'){ // 如果不是buffer和string
data = JSON.stringify(data);
}
res.write(data);
}
//不是接口
if(router.emit(pathname,req ,res)==false){
//读取文件
res.setHeader('Content-Encoding','gzip');
let rs = fs.createReadStream(`www${pathname}`);
let gz = zlib.createGzip();
rs.pipe(gz).pipe(res);
rs.on('error',err=>{
res.writeHeader(404);
res.write('not found');
res.end();
});
}else{ // 是接口
}
}).listen(8080);
-------------------------------------------------------------------------------------------------
user.js:
let router = require('../libs/router');
// 用户登录注册接口
let users = {};
router.on('/login',(req,res)=>{
let {user,pass} = req.query;
if(!users[user]){
res.send({code:'1',msg: '用户名不存在'});
res.end();
}else if(users[user]!=pass){
res.send({code:'1',msg: '用户登录密码错误'});
res.end();
}else{
res.send({code:'0',msg:'登录成功'});
res.end();
}
});
router.on('/reg',(req,res)=>{
let {user,pass} = req.query;
if(users[user]){
res.send({code:'1',msg: '用户已存在'});
res.end();
}else{
users[user] = pass;
res.send({code:'0',msg: '注册成功'});
res.end();
}
})
router.js:
let Event = require('events').EventEmitter;
module.exports = new Event();
6.Cluster(集群(多进程))
//多进程
const cluster = require('cluster');
const http = require('http');
const url = require('url');
const fs = require('fs');
const numCups = require('os').cpus().length;
const process = require('process');
if(cluster.isMaster) {
console.log(`主进程${process.pid}正在运行`);
// 创建子进程
for(let i=0; i<numCups;i++){
cluster.fork();
}
}else{
http.createServer((req,res) => {
res.writeHeader(200);
res.write('hello world\n')
}).listen(8080);
console.log(`${process.pid}进程正在运行`);
}
7.crypto(加密)
const crypto = require('crypto');
let md5 = crypto.createHash('md5');
md5.update(pass);
pass = md5.digest('hex');