Nodejs的非阻塞IO、异步以及 事件驱动EventEmitter解决异步 (7)

1Nodejs 的单线程 非阻塞 I/O 事件驱动   

Node.js 不为每个客户连接创建一个新的线程, 而仅仅使用一个线程。当有用户连接了,
就触发一个内部事件,通过非阻塞 I/O、事件驱动机制,让 Node.js 程序宏观上也是并行的。
使用 Node.js,一个 8GB 内存的服务器,可以同时处理超过 4 万用户的连接

2 异步IO执行过程

console.log('1');

// fs.readFile 是非阻塞IO
fs.readFile('mime.js',function (err,data) {
    console.log('2');
});

console.log('3');

 

执行结果

 

 

 

2异步存在的问题

// 错误写法

// 非阻塞io 引发的问题
function getMime() {
    console.log('1'); // 1
    fs.readFile('mime.json',function(err,data){
        console.log('2');  // 2
        return data.toString();
    });
    console.log('3'); // 3
}

console.log(getMime()); // undefined

 

执行结果,获取不到文件内容

 

3 回调解决异步问题

// 正确写法
var fs = require('fs');
// 回调 callback
function getMime(callback) {
    fs.readFile('mime.json',function(err,data){
        callback(data); //使用回调传值
    });
}

getMime(function (result) {
    console.log(result.toString()); // 回调过程中获取值
}); // 执行函数

 

 

4  事件驱动

1. nodejs 事件循环:

  nodejs 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高;

  nodejs 的每一份api都是异步的,并作为一个独立线程运行,使用一步函数调用,并处理并发;

  nodejs 有多个内置的事件,我们可以通过引入 events 模块,并实例化 EventEmitter 类来绑定和监听事件.

 

// 引入 events 模块

var events=require('events');

//console.log(events);

// 实例 EventEmitter 监听和广播 事件对象
var EventEmitter=new events.EventEmitter();

//广播 和接收广播

EventEmitter.on('to_mime',function(data){

    console.log(data);

});

//监听to_parent的广播
EventEmitter.on('to_parent',function(data){
    //console.log('接收到了这个广播事件');

    console.log(data);

    EventEmitter.emit('to_mime','给mime发送的数据')

});

setTimeout(function(){
    console.log('开始广播...');
    //广播to_parent事件
    EventEmitter.emit('to_parent','给to_parent发送的数据')

},1000);

 

 

 

执行结果

 

 

 

5 使用事件驱动解决异步问题

 

var fs = require('fs');
var events = require('events');
var EventEmitter = new events.EventEmitter();

function getMime() {
    fs.readFile('mime.json',function(err,data){
        EventEmitter.emit('mime',data) // 事件传值
    });
}

getMime(); //执行函数

// 监听 mime 事件
EventEmitter.on('mime',function (data) {
    console.log(data.toString());
});

 

6 get 和post 请求

//引入http模块
var http=require('http');

var url=require('url');

var ejs=require('ejs');

var fs=require('fs');

//路由:指的就是针对不同请求的 URL,处理不同的业务逻辑。
http.createServer(function(req,res){
    res.writeHead(200,{"Content-Type":"text/html;charset='utf-8'"});

    //获取get 还是post请求
    var method=req.method.toLowerCase();
    //console.log(method);
    var pathname=url.parse(req.url,true).pathname;

    if(pathname==='/login'){  /*显示登录页面*/


        ejs.renderFile('views/form.ejs',{

        },function(err,data){
            res.end(data);
        })}else if(pathname==='/dologin' &&method==='get'){
        //get获取数据
        console.log(url.parse(req.url,true).query);
        res.end('dologin');
    }else if(pathname==='/dologin' &&method==='post'){
        //post获取数据
        var postStr ='';
        req.on('data',function (chunk) {
            postStr +=chunk;
        });

        req.on('end',function (err,chunk) {
            console.log(postStr);
            fs.appendFile('login.txt',postStr +'\n',function (err) {
                if (err){
                    console.log(err);
                }
                console.log('写入文件成功');
            })

        })
    }else{
        res.end('other')
    }
}).listen(8001);

 

posted @ 2019-10-25 16:19  柳帅  阅读(357)  评论(0编辑  收藏  举报
//替换成自己路径的js文件