Node简介
Node应该是如今最火热的技术了,接下来开始介绍Node
1.Node的诞生历程
Node的诞生历程如下所示:
- 2009年2月,Ryan Dahl在博客上宣布准备基于V8创建一个轻量级的Web服务器并提供一套库。
- 2009年5月,Ryan Dahl在GitHub上发布了最初版本的部分Node包,随后几个月里,有人开始使用Node开发应用。
- 2009年11月和2010年4月,两届JSConf大会都安排了Node.js的讲座。
- 2010年年底,Node获得云计算服务商Joyent资助,创始人Ryan Dahl加入Joyent全职负责Node的发展。
- 2011年7月,Node在微软的支持下发布Windows版本。
- 2011年11月,Node超越Ruby on Rails,成为GitHub上关注度最高的项目。
- 2012年1月底,Ryan Dahl在对Node架构设计满意的情况下,将掌门人的身份转交给Isaac Z. Schlueter,自己转向一些研究项目。Isaac Z. Schlueter是Node的包管理器NPM的作者,之后Node的版本发布和bug修复等工作由他接手。
2. Node的起源
Ryan Dahl是一名资深的C/C++程序员,在创造出Node之前,他的主要工作都是围绕高性能Web服务器进行的。经历过一些尝试和失败之后,他找到了设计高性能Web服务器的几个要点:事件驱动、非阻塞I/O。
所以在评估了C、Lua、Haskell、Ruby等语言后,选中了JavaScript。另外,javaScript在浏览器中有广泛的事件驱动方面的应用,暗合Ryan Dahl喜好基于事件驱动的需求。当时,第二次浏览器大战也渐渐分出高下,Chrome浏览器的JavaScript引擎V8摘得性能第一的桂冠,而且基于新BSD许可证发布,自然受到Ryan Dahl的欢迎。JavaScript成为了Node的实现语言。
3.Node的特点
作为后端JavaScript的运行平台,Node保留了前端浏览器JavaScript中那些熟悉的接口,没有改写语言本身的任何特性,依旧基于作用域和原型链,区别在于它将前端中广泛运用的思想迁移到了服务器端。
3.1 异步 I/O
异步I/O机制,因此在执行访问数据库的代码之后,将立即去执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,每个调用之间无需等待之前的I/O调用结束,提高了程序的执行效率。
$.post('/url',function(data){
console.log('收到数据')
});
console.log('发送数据')
熟悉异步的必然知道“收到数据”是在“发送数据”之后输出的。在调用$.post()后,后续代码是被立即执行的,而“收到数据”的执行时间是不被预期的。我们只知道它将在这个异步请求结束之后执行,但不知道具体的时间。
3.2事件与回调函数
在node中,一个时刻只能执行一个事件回调函数,但在执行一个事件回调函数的过程中,可以转而处理其他事情,然后返回继续执行原事件的回调函数.。与其他web后端编程语言相比,node除了异步和事件外,回调函数也是一大特色,回调函数也是最好的接受异步调用返回数据的方式。
3.3 单线程
Node保持了JavaScript在浏览器中单线程的特点。而且在Node中,JavaScript 与其余线程是无法共享任何状态的。
好处:
单线程最大的好处是不用像多线程编程那样处处在意状态的同步问题。没有线程上下文交换带来的性能上的消耗。
缺点:
- 无法利用多核CPU
- 错误会引起整个应用退出
- 大量计算占用CPU导致无法继续调用异步I/O
3.4 跨平台
起初,Node只可以在Linux平台上运行。如果想在Windows平台上学习和使用Node,则必须通过Cygwin或者MinGW。随着Node的发展,微软注意到了它的存在,并投入了一个团队帮助Node实现Windows平台的兼容,在v0.6.0版本发布时,Node已经能够直接在Windows平台上运行了。
4.模块
在Node中,所有功能均已被封装成模块,默认开发模块开发其中开启服务中需要用到的模块:
http模块:用来开启服务
fs模块:用来操作模块
url模块:用来解析url
querystring模块:用来解析url携带的数据
http模块:
//1.引入模块
const http = require("http”);
//2.开启一个http服务,接收的回调函数中,有两个返回值,req表示请求(客户端到服务端),res表示响应(服务端到客户端)
const httpObj = http.createServer((req,res)=>{…})
//创建服务成功后,每次请求都会触发createServer的回调函数
const httpObj = http.createServer((req,res)=>{
//http请求默认情况下,会多请求一次favicon.ico图标文件,如不需要可以过滤
if(req.url != "/favicon.ico"){
//可以在服务端打印信息,只要被访问就会触发
console.log("有人访问了");
//参数req有属性为url,表示当前服务被哪个url访问,打印访问服务的url
console.log("访问的地址是:" + req.url);
//如果需要向前端返回数据,而且数据需要以html的形式被解析,有两种方式:
// 1.通过head和meta标签设置字符编码
//res.write("<head><meta charset='utf-8'></head>");
// 2.通过设置请求头,设置字符编码(推荐)
res.writeHead(200,{"content-type":"text/html;charset=utf-8"})
//通过参数res的write方法,向前端返回数据,此处打印标签进行测试
res.write("<mark>测试</mark>")
//完成此次请求的响应之后,要结束本次响应,否则前端会一直处在请求状态
res.end()
}
})
//3.监听端口地址,成功开启服务,执行回调函数...
httpObj.listen("3000","127.0.0.1",()=>{
console.log("server runing...");
});
fs模块:
//引入fs(文件系统)模块
const fs = require('fs’);
//调用fs模块的读取文件方法,接收三个参数:
//参数1:指定读取文件名为请求的文件名
//参数2:指定解析文件内容的编码格式,可省略
//参数3:回调函数,读取文件后执行,接收两个参数
//参数1:错误日志,或,null
//参数2:文件内容
fs.readFile("./www/index.html","utf-8",(err,fsCont)=>{
if(err){
//如果不为null,表示有错误内容,响应404
res.write("404")
}else{
//如果为null,表示找到文件,将文件作为数据响应
res.write(fsCont)
}
res.end(); //结束本次请求
})
url模块:
//引入url模块
const urlModel = require("url");
//模拟一个url
var url = "http://www.baidu.com/data/hahaha/?a=1&b=2#01";
console.log(typeof url);
console.log(url);
//将url解析成对象
var obj = urlModel.parse(url);
var obj = urlModel.parse(url,true); //将url中的query属性解析成对象
console.log(typeof obj);
console.log(obj);
//将对象解析成url
var str = urlModel.format(obj);
console.log(typeof str);
console.log(str);
querystring模块:
//将查询字符与对象互相转换的模块
const querystring = require("querystring");
//模拟类似于get方式发送的信息
var str = 'name=admin%padd=123';
//根据%号,分割字符为对象
var obj = querystring.parse(str,"%");
console.log(typeof obj);
console.log(obj);
//模拟对象
var obj2 = {a:1,b:2}
console.log(obj2)
//将对象转换成类似于get方式发送的信息,用%号隔开
var str2 = querystring.stringify(obj2,"%");
console.log(typeof str2)
console.log(str2)
就分享这么多了,
有误的地方请多多指教。