一、处理I/O
1.异步非阻塞I/O
关于上述概念,网上有一个很经典的响水壶解释
隔壁王大爷有个水壶,王大爷经常用它来烧水。
(同步阻塞):王大爷把水壶放到火上烧,然后啥也不干,就在那等,直到水烧开了王大爷再去干别的事情。
(同步非阻塞):王大爷觉得自己有点憨,不打算等了,把水壶放上去之后就去看剧了,时不时来瞅一眼水有没有开。
(异步阻塞):王大爷去买了响水壶,他把壶放到火上,然后也是等着水开,水开的时候水壶会发出声响。
(异步非阻塞):王大爷觉得有点憨,他把水壶放到火上然后去看剧,也不用时不时瞅一眼,因为水开的时候水壶会发出声音通知大爷。
//03-fs.js
const fs=require('fs');
//同步调用
const data=fs.readFileSync('./conf.js');//代码会阻塞在这里
console.log(data);
//异步调用
fs.readFile('./conf.js',(err,data)=>{
if(err) throw err;
console.log(data);
})
//promisify
const{
promisify}=require('util')
constreadFile=promisify(fs.readFile)
readFile('./conf.js').then(data=>console.log(data))
//fs Promises API node v10
const fsp=require("fs").promises;
fsp
.readFile("./confs.js")
.then(data=>console.log(data))
.catch(err=>console.log(err));
//async/await
(async()=>{
const fs=require('fs')
const{
promisify}=require('util')
const readFile=promisify(fs.readFile)
const data=await readFile('./index.html')
console.log('data',data)
})()
//引用方式
Buffer.from(data).toString('utf-8')
二、Buffer缓冲区
读取数据类型为Buffer
Buffer - 用于在TCP流、文件系统操作、以及其他上下文中与八位字节进行交互。八位字节组成的数据,可以有效的在Js中储存二进制数据。
//04-buffer.js
//创建一个长度为10字节以0填充的Buffer
const buf1=Buffer.alloc(10);
console.log(buf1);
//创建一个Buffer包含ascii.
//ascii查询http://ascii.911cha.com/
const buf2=Buffer.from('a')
console.log(buf2,buf2.toString())
//创建Buffer包含UTF-8字节
//UFT-8:一种变长的编码方案,使用1~6个字节来存储;
//UFT-32:一种固定长度的编码方案,不管字符编号大小,始终使用4个字节来存储;
//UTF-16:介于UTF-8和UTF-32之间,使用2个或者4个字节来存储,长度既固定又可变。
const buf3=Buffer.from('Buffer创建方法');
console.log(buf3);
//写入Buffer数据
buf1.write('hello');
console.log(buf1);
//读取Buffer数据
console.log(buf3.toString());
//合并Buffer
const buf4=Buffer.concat([buf1,buf3]);
console.log(buf4.toString());
//可以尝试修改fs案例输出文件原始内容
Buffer 类似数组,所以很多数组方法它都有GBK转码 iconv-lite
三、HTTP服务
创建一个HTTP服务器,05-http.js
http=require('http');
const server=http.createServer((request,response)=>{
console.log('thereisarequest');
response.end('aresponsefromserver');
});
server.listen(3000);
//打印原型链
functiongetPrototypeChain(obj){
varprotoChain=[];
while(obj=Object.getPrototypeOf(obj)){
//返回给定对象的原型。如果没有继承属性,则返回null。
protoChain.push(obj);
}
protoChain.push(null);
return protoChain;
}
显示一个首页
const{
url,method}=request;
if(url==='/'&&method==='GET'){
fs.readFile('index.html',(err,data)=>{
if(err){
response.writeHead(500,{
'Content-Type':'text/plain;charset=utf-8'});
response.end('500,服务器错误');
return;
}
response.statusCode=200;
response.setHeader('Content-Type','text/html');
response.end(data);
});
}else{
response.statusCode=404;
response.setHeader('Content-Type','text/plain;charset=utf-8');
response.end('404,页面没有找到');
}
编写一个接口
elseif(url==='/users'&&method==='GET'){
response.writeHead(200,{
'Content-Type':'application/json'});
response.end(JSON.stringify([{
name:'tom',age:20}]));
}
四、stream流
stream - 是用于与node中数据流交互的接口
//二进制友好,图片操作,06-stream.js
const fs=require('fs')
const rs2=fs.createReadStream('./01.jpg')
const ws2=fs.createWriteStream('./02.jpg')
rs2.pipe(ws2);
//响应图片请求,05-http.js
const{
url,method,headers}=request;
elseif(method==='GET'&&headers.accept.indexOf('image/*')!==-1){
fs.createReadStream('.'+url).pipe(response);
}
Accept代表发送端(客户端)希望接受的数据类型。比如:Accept:text/xml;代表客户端希望接受的数据类型是xml类型。
Content-Type代表发送端(客户端|服务器)发送的实体数据的数据类型。比如:Content-Type:text/html;代表发送端发送的数据格式是html。
二者合起来,Accept:text/xml;Content-Type:text/html,即代表希望接受的数据类型是xml格式,本次请求发送的数据的数据格式是html。