Nodejs 的非阻塞 I/O、 异步、 事件驱动
Nodejs 的单线程 非阻塞 I/O 事件驱动
在 Java、 PHP 或者.net 等服务器端语言中,会为每一个客户端连接创建一个新的线程。
而每个线程需要耗费大约 2MB 内存。也就是说,理论上,一个 8GB 内存的服务器可以同时
连接的最大用户数为 4000 个左右。要让 Web 应用程序支持更多的用户,就需要增加服务器
的数量,而 Web 应用程序的硬件成本当然就上升了。
Node.js 不为每个客户连接创建一个新的线程, 而仅仅使用一个线程。当有用户连接了,
就触发一个内部事件,通过非阻塞 I/O、事件驱动机制,让 Node.js 程序宏观上也是并行的。
使用 Node.js,一个 8GB 内存的服务器,可以同时处理超过 4 万用户的连接
Nodejs 回调处理异步
//错误的写法: function getData(){ //模拟请求数据 var result=''; setTimeout (function(){ result='这是请求到的数据' },200); return result; } console.log(getData());/*异步导致请求不到数据*/
//正确的处理异步: function getData(callback){ //模拟请求数据 var result=''; setTimeout (function(){ result='这是请求到的数据'; callback(result); },200); } getData(function(data){ console.log(data); })
Nodejs events 模块处理异步
Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter类来绑定和监听事件。
// 引入 events 模块 var events = require('events'); var EventEmitter=new events.EventEmitter(); /*实例化事件对象*/ EventEmitter.on('toparent',function(){ console.log('接收到了广播事件'); }) setTimeout (function(){ console.log('广播'); EventEmitter.emit('toparent'); /*发送广播*/ },1000)
案例:
getmimefromfile.js
exports.getMime=function(fs,extname,callback){ /*获取后缀名的方法*/ fs.readFile('./mime.json',function(err,data){ if(err){ console.log('mime.json文件不存在'); return false; } //console.log(data.toString()); var Mimes=JSON.parse(data.toString()); var result= Mimes[extname] || 'text/html'; callback(result) }) }
getmimefromfile_events.js
exports.getMime=function(fs,EventEmitter,extname){ /*获取后缀名的方法*/ fs.readFile('./mime.json',function(err,data){ if(err){ console.log('mime.json文件不存在'); return false; } //console.log(data.toString()); var Mimes=JSON.parse(data.toString()); var result= Mimes[extname] || 'text/html'; EventEmitter.emit('to_mime',result); }) }
one.js:
//引入http模块 var http=require('http'); //fs模块 var fs=require('fs'); //path模块 var path=require('path'); /*nodejs自带的模块*/ //url模块 var url=require('url'); //引入扩展名的方法是在文件里面获取到的。 var mimeModel=require('./model/getmimefromfile.js'); //console.log(mimeModel.getMime('.css')); //获取文件类型 http.createServer(function(req,res){ //http://localhost:8001/news.html /news.html //http://localhost:8001/index.html /index.html //css/dmb.bottom.css //xxx.json?214214124 var pathname=url.parse(req.url).pathname; console.log(pathname); if(pathname=='/'){ pathname='/index.html'; /*默认加载的首页*/ } //获取文件的后缀名 var extname=path.extname(pathname); if(pathname!='/favicon.ico'){ /*过滤请求favicon.ico*/ //console.log(pathname); //文件操作获取 static下面的index.html fs.readFile('static/'+pathname,function(err,data){ if(err){ /*么有这个文件*/ console.log('404'); fs.readFile('static/404.html',function(error,data404){ if(error){ console.log(error); } res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"}); res.write(data404); res.end(); /*结束响应*/ }) }else{ /*返回这个文件*/ var mime=mimeModel.getMime(fs,extname,function(mime){ res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"}); res.write(data); res.end(); /*结束响应*/ }); } }) } }).listen(8002);
two.js
//引入http模块 var http=require('http'); //fs模块 var fs=require('fs'); //path模块 var path=require('path'); /*nodejs自带的模块*/ //url模块 var url=require('url'); var events=require('events'); var EventEmitter=new events.EventEmitter(); var mimeModel=require('./model/getmimefromfile_events.js'); //引入扩展名的方法是在文件里面获取到的。 //console.log(mimeModel.getMime('.css')); //获取文件类型 http.createServer(function(req,res){ //http://localhost:8001/news.html /news.html //http://localhost:8001/index.html /index.html //css/dmb.bottom.css //xxx.json?214214124 var pathname=url.parse(req.url).pathname; console.log(pathname); if(pathname=='/'){ pathname='/index.html'; /*默认加载的首页*/ } //获取文件的后缀名 var extname=path.extname(pathname); if(pathname!='/favicon.ico'){ /*过滤请求favicon.ico*/ //console.log(pathname); //文件操作获取 static下面的index.html fs.readFile('static/'+pathname,function(err,data){ if(err){ /*么有这个文件*/ console.log('404'); fs.readFile('static/404.html',function(error,data404){ if(error){ console.log(error); } res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"}); res.write(data404); res.end(); /*结束响应*/ }) }else{ /*返回这个文件*/ mimeModel.getMime(fs,EventEmitter,extname); /*调用获取数据的方法*/ EventEmitter.on('to_mime',function(mime){ res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"}); //res.write(data); res.end(data); /*结束响应*/ }) } }) } }).listen(8002);
最后,关注【码上加油站】微信公众号后,有疑惑有问题想加油的小伙伴可以码上加入社群,让我们一起码上加油吧!!!