最近看《node即学即用》,做点笔记~~
一、核心API
1.【Events】
**浏览器中的事件模型是从DOM中来的
**DOM是基于用户交互的用户驱动型事件模型,有着一组与树状结构对应的接口元素
**当用户与接口的某个特定部分交互时,对应有一个事件和一个相关的对象
**操作对象是在一棵树上,故模型包含了冒泡和捕获的概念,即可以沿着树向上或向下的元素也接收到被触发的事件
**javascript的事件模型没有树状结构,故更为简洁
【EventEmitter】提供基础的事件功能
【on方法】监听事件
1 server.on(‘event‘,function(a,b,c){ 2 //具体操作 3 });
【创建一个新类支持EventEmitter事件】
var utils=requires(‘utils‘);//引入utils模块,可以调用inherits方法
var EventEmitter=require(‘events‘).EventEmitter;
var Server=function(){
console.log(‘init‘);
};
//把EventEmitter类的方法添加到创建的Server类中
//所有的Server新实例都可以使用EventEmitter方法
utils.inherits(Server,EventEmitter);
var s=new Sever();
s.on(‘abc‘,function(){
console.log(‘abc‘);
});
【emit方法】触发一个事件
1 s.emit(‘abc‘)
**这些事件是针对某个对象的,不存在全局的事件
【Callback原理】
1.触发事件时传递参数
1 s.emit(‘abc‘,a,b,c); 2 3 http.emit(‘request‘,req,res);
2.触发器中如何调用事件
1 if(arguments.length<=3){ 2 //速度快 3 handler.call(this,arguments[1],arguments[2]); 4 }else{ 5 //速度慢 6 var args=Array.prototype.slice.call(arguments,1); 7 handler.apply(this,args); 8 } 9
**参数少时,直接用call方法;参数多时,用apply方法,用数组来传递参数
**用到了this--->事件监听器被调用时在EventEmitter的上下文中,而不是原来的位置
2.【HTTP】
【HTTP服务器】
**创建简单HTTP服务器
1 var http=require(‘http‘); 2 var server=http.createServer(); 3 var handleReq=function(req,res){ 4 res.writeHead(200,{}); 5 res.end(‘hello world!‘); 6 }; 7 server.on(‘request‘,handleReq); 8 server.listen(8125);
**HTTP的事件们:
【request】有新的HTTP请求
【checkContinue】客户端以数据流方式将数据发送给服务器时调用,检查当前状态下是否继续;
如果这个事件绑定了事件触发器,request请求就不会被触发
【upgrade】客户端请求协议升级时会触发,除非绑定了此事件的事件处理器,否则http服务器将拒绝请求
【clientError】把客户端发送的error事件传递出来
【Connection】为请求创建一个新的TCP流时触发,事件会把TCP流作为参数传给该请求
该数据流也可以在request使用的时候,通过request.connection变量获得
但每个流只会触发connection事件一次--->可能会出现从一个客户端来多个请求只对应一次connection事件
【close】客户端TCP的关闭
【HTTP客户端】
【提交HTTP GET请求】
1 var http=require(‘http‘); 2 3 var opts={ 4 host:‘www.google.com‘, 5 port:80, 6 path:‘/‘ 7 }; 8 9 var req=http.get(opts,function(){ 10 console.log(res); 11 res.setEncoding(‘utf8‘);//设置编码 12 res.on(‘data‘,function(data){ 13 console.log(data); //得到Buffer对象的裸数据 14 }); 15 });
【发送HTTP POST和PUT数据】
1 var http=require(‘http‘); 2 3 var options={ 4 host:‘www.example.com‘, 5 port:80, 6 path:‘/submit‘, 7 method:‘POST‘ 8 }; 9 10 var req=http.request(options,function(res){ 11 res.setEncoding(utf8); 12 res.on(‘data‘,function(chunk){ 13 console.log(‘BODY: ‘+chunk); 14 }); 15 }); 16 17 req.write("my data"); 18 req.write("more of my data"); 19 20 req.end();
【ClientResponse对象】保存了关于请求的许多信息,包括statusCode(包含了HTTP状态)和header(响应头对象)
【URL】提供了解析和处理URL字符串的便利工具
【parse方法】解析URL
1 var URL=require(‘url‘); 2 var myUrl="http://www.nodejs.org/some/url/?with=query¶m=that&are=awesome#alsoahash"; 3 4 var parsedUrl=URL.parse(myUrl); 5 var parsedUrl2=URL.parse(myUrl,true);
【结果分析】解析出来的parsedUrl包括以下几个部分
1.href:原始输入用来解析的完整URL
2.protocol:URL中的协议(如:http: https: ftp:)
3.host:URL中完整的hostname(可以是本地服务器hostname,也可以是域名)
【细分】auth(包含用户证书)、port(单纯端口)、hostname(完整的hostname)
4.pathname:跟在host后面的整个文件路径
5.search:URL中HTTP GET参数(上例中为:‘?with=query¶m=that&are=awesome‘)
6.query:类似于search,少了?(缺省或false时,query:‘with=query¶m=that&are=awesome‘)
(true时,用querystring模块解析,query:{with:‘query‘,param:‘that‘,are:‘awesome‘})
7.hash:片段部分,#后(上例中,hash:‘#alsoahash‘)
【querystring】1)parse方法(见上,注意:数字是返回成字符串的;传入的query字符不能包含?)
2)encode方法(把输入的key-value格式的对象转换成query字符串形式)
3.【I/O】
【数据流】数据流包括可读、可写和可读写
【创建可读文件流】
1 var fs=require(‘fs‘); 2 var filehandle=fs.readFile(‘data.txt‘,function(err,data){ 3 console.log(data); 4 });
【使用缓冲池模型来读取完整的流数据】
1 //stream是个抽象的数据流 2 var spool=""; 3 stream.on(‘data‘,function(data){ 4 spool+=data; 5 }); 6 stream.on(‘end‘,function(){ 7 console.log(spool); 8 });
【文件系统】要注意运行的顺序
【错误的代码--异步读取并删除文件】
1 var fs=require(‘fs‘); 2 3 fs.readFile(‘warandpeace.txt‘,function(e,data){ 4 console.log(‘War and Peace: ‘+ data); 5 }); 6 7 fs.unlink(‘warandpeace.txt‘);
【正确的代码--通过嵌入回调函数完成异步读取并删除文件】
var fs=require(‘fs‘); fs.readFile(‘warandpeace.txt‘,function(e,data){ console.log(‘War and Peace: ‘+data); fs.unlink(‘warandpeace.txt‘); });
【Buffer】是对内存的直接分配;处理二进制数据;未处理时用十六进制表示;创建一个Buffer后大小就固定了,要添加数据要将其复制到一个更大的Buffer中
【ASCII and UTF】ASCII:7位大小,128个,第8位用来扩展字符集;字符串长度等于字节数长度;
UTF:头128个是ASCII,罕见字符时,第一个字节代表第二页位置,第二个字节代表第三页位置;字符串长度不等于字节数长度;
【二进制 and 字符串】Buffer大小最好定为可能输入的UTF字符最大值的4倍大小---可以保证完整的保存字符串内容
【创建Buffer】三种方法:
1.指定字节长度创建Buffer new Buffer(10); //会给出脏数据填补空间
2.用字符串创建Buffer new Buffer(‘foobarbaz‘,‘ascii‘); //默认是utf8,也可以改成ascii
3.Buffer.write(字符串,位置) 写入数据---返回写入的字符个数,在写入utf8时,在允许的情况下,会在结尾带上NULL(\\00)
1 var b=new Buffer(5); 2 3 b.write(‘fffff‘); //返回5,b为<Buffer 66 66 66 66 66> 4 5 b.write(‘ab‘,1); //返回2,b为<Buffer 66 61 62 00 66>
【console.log】直接输出,并且能够美化格式