node——模块化

之前写的新闻部分几乎所有操作都写在了一起,这次开始进行模块化。

为什么要模块化:

1.提高开发效率,所有操作在一个文件内,不方便团队操作,模块化可多人同时操作

2.当程序出错,可以分模块寻找错误

3.可以使程序不一次性全部展示出来,保留一些操作不可见

模块化步骤:

1.思考,该模块中要封装什么代码?

2.思考,这些代码有用到什么外部数据?如果用到了该如何传递
3.当前模块对外需要暴露的东西(moudule.eports的值)

原代码:

var http=require('http');
var fs=require('fs');
var path=require('path');
var mime=require('mime');
var url=require('url');
var querystring=require('querystring');
var _=require('underscore');

http.createServer(function(req,res){

res.render=function(filename,tqData){
    fs.readFile(filename,function(err,data){
        if(err)
        {
            res.writeHead(404,'Not Found',{'Content-Type':'text/html;charset=utf-8'});
            res.end('44,not found');
            return;
        }
        if(tqData){
            var fn=_.template(data.toString('utf8'));
            data=fn(tqData);

        }
        res.end(data);
    })

}



req.url=req.url.toLowerCase();
req.method=req.method.toLowerCase();

var urlObj=url.parse(req.url,true);

if(req.url==='/'||req.url==='/index'&&req.method==='get')
{
    readNewsData(function(list){
        res.render(path.join(__dirname,'views','home.html'),{list:list});
    })

}else if(req.url==='/submit'&&req.method==='get'){

    res.render(path.join(__dirname,'views','submit.html'));
        
}else if(urlObj.pathname==='/item'&&req.method==='get'){

readNewsData(function(list){

        for(var i=0;i<list.length;i++)
        {

            if(list[i].id.toString()===urlObj.query.id)
            {
                model=list[i];
                break;

            }
        }
        if(model)
        {
            res.render(path.join(__dirname,'views','details.html'),{item:model});
        }
        else
        {
            res.end('no found')
        }
    })

}else if(req.url.startsWith('/add')&&req.method==='get'){

    fs.readFile(path.join(__dirname,'data','data1.json'),'utf8',function(err,data){
        if(err&&err.code!=='ENOENT'){
            throw err;
        }
        var list_news=JSON.parse(data||'[]');
        
    });

    
    
        
}else if(req.url.startsWith('/add')&&req.method==='post'){
        
        readNewsData(function(list_news){
            
            postBodyData(req,function(postBody){
            
            postBody.id=list_news.length;
            list_news.push(postBody);
            
            writeNewsData(JSON.stringify(list_news),function(){
            res.statusCode=302;
            res.statusMessage='Found';
            res.setHeader('Location','/');
            res.end('over');

                });
        });
    });

    
}else if(req.url.startsWith('/resource')&&req.method==='get'){


    res.render(path.join(__dirname,req.url));

}        
else{
    res.writeHead(404,'NOT FOUND',{
        'Content-Type':'text/plain;charset=utf-8'
    });
    res.end('404,page not found');
}
}).listen(9090,function(){
    console.log('http://localhost:9090');
})


function readNewsData(callback){
    fs.readFile(path.join(__dirname,'data','data1.json'),'utf8',function(err,data){
        if(err&&err.code!=='ENOENT'){
            throw err;
        }

        var list_news=JSON.parse(data||'[]');
        //通过回调函数callback()将读取到的数据list,传递出去
        callback(list_news);
    });
}


function writeNewsData(data,callback){
    fs.writeFile(path.join(__dirname,'data','data1.json'),data,function(err){
        if(err){
            throw err;
        }
        console.log('ok');
    });

        callback();
}


function postBodyData(req,callback){
    
            var array=[];
        req.on('data',function(chunk){
            array.push(chunk);
    
        });

        req.on('end',function(){
            var postBody=Buffer.concat(array);
            postBody=postBody.toString('utf8');
            
            postBody=querystring.parse(postBody);
        
        callback(postBody);
        });
}
View Code

模块化部分:

模块一(服务模块):负责启动服务
模块二(扩展模块):负责扩展req和res对象,为res和res对象,为req和res增加以下更方便更好用的API
模块三(路由模块):负责路由判断
模块四(业务模块):负责处理具体路由的业务的代码

模块一(index.js)

代码:

 1 var http=require('http');
 2 var context=require('./context.js');
 3 var router=require('./router.js');
 4 var handler=require('./handler.js');
 5 
 6 http.createServer(function(req,res){
 7     //调用context.js模块的返回值(函数),并将req和res对象传递给context.js模块
 8     context(req,res);
 9     //调用路由模块返回值
10     router(req,res);
11 
12 
13 }).listen(9090,function(){
14     console.log('http://localhost:9090');
15 })
View Code

模块二(context.js)

负责扩展req和res对象,为res和res对象,为req和res增加以下更方便更好用的API
希望在该模块做:
1.为req增加一个query熟悉,该属性中保存的就是用户get请求提交过来的数据
-req.query
2.为req增加一个pathname属性
-req.pathname
3.为res增加一个render函数

代码:

var http=require('http');
var fs=require('fs');
var path=require('path');
var mime=require('mime');
var url=require('url');
var querystring=require('querystring');
var _=require('underscore');

//让当前模块对外暴露一个函数,通过这个函数将res,req传入模块中
module.exports=function(req,res){

    //1.为req增加query属性
    var urlObj=url.parse(req.url.toLowerCase(),true);
    req.query=urlObj.query;
    //2.为req增加pathname属性
    req.pathname=urlObj.pathname;
    //3.为req增加method属性
    req.method=req.method.toLowerCase();

    //3.为res增加函数
    res.render=function(filename,tqData){
        fs.readFile(filename,function(err,data){
            if(err)
            {
                res.writeHead(404,'Not Found',{'Content-Type':'text/html;charset=utf-8'});
                res.end('44,not found');
                return;
            }
            if(tqData){
                var fn=_.template(data.toString('utf8'));
                data=fn(tqData);

            }
            res.end(data);
        });
    };

};
View Code

模块三(router.js)

该模块负责封装所以路由判断代码

代码:

 1 //该模块负责封装所以路由判断代码
 2 
 3 var handler=require('./handler');
 4 
 5 
 6 module.exports = function(req,res){
 7     if(req.url==='/'||req.url==='/index'&&req.method==='get')
 8 {
 9     handler.index(req,res);
10 
11 }else if(req.pathname==='/submit'&&req.method==='get'){
12     handler.submit(req,res);
13         
14 }else if(req.pathname==='/item'&&req.method==='get'){
15     handler.item(req,res);
16 
17 }else if(req.url.startsWith('/add')&&req.method==='post'){
18     handler.add(req,res);
19     
20 }else if(req.url.startsWith('/resource')&&req.method==='get'){
21     handler.resource(req,res);
22 
23 }        
24 else{
25     handler.nofound(req,res);
26 }
27 }
View Code

模块四(handler.js)

该模块负责对具体的业务进行处理

代码:

  1 //该模块负责对具体的业务进行处理
  2 var path=require('path');
  3 var fs=require('fs'); 
  4 var querystring=require('querystring');
  5 
  6 module.exports.index=function(req,res){
  7     if(req.pathname==='/'||req.url==='/index'&&req.method==='get')
  8     {
  9     readNewsData(function(list){
 10         res.render(path.join(__dirname,'views','home.html'),{list:list});
 11     })
 12 }}
 13 
 14 module.exports.submit=function(req,res){
 15     res.render(path.join(__dirname,'views','submit.html'));
 16 }
 17 
 18 module.exports.item=function(req,res){
 19     readNewsData(function(list){
 20 
 21         for(var i=0;i<list.length;i++)
 22         {
 23 
 24             if(list[i].id.toString()===req.query.id)
 25             {
 26                 model=list[i];
 27                 break;
 28 
 29             }
 30         }
 31         if(model)
 32         {
 33             res.render(path.join(__dirname,'views','details.html'),{item:model});
 34         }
 35         else
 36         {
 37             res.end('no found')
 38         }
 39     })
 40 
 41 }
 42 
 43 
 44 module.exports.add=function(req,res){
 45     //1.读取data1.json
 46         readNewsData(function(list_news){
 47             //2.读取用户post提交的数据
 48             postBodyData(req,function(postBody){
 49             //3.为用户提交的新闻增加一个id属性,并且把新闻对象push到list中
 50             postBody.id=list_news.length;
 51             list_news.push(postBody);
 52             //将list数组写入到data1.json中
 53             writeNewsData(JSON.stringify(list_news),function(){
 54             res.statusCode=302;
 55             res.statusMessage='Found';
 56             res.setHeader('Location','/');
 57             res.end('over');
 58 
 59                 });
 60         });
 61     });
 62 
 63 }
 64 
 65 
 66 module.exports.resource=function(req,res){
 67     res.render(path.join(__dirname,req.pathname));
 68 }
 69 
 70 
 71 module.exports.nofound=function(req,res){
 72     res.writeHead(404,'NOT FOUND',{
 73         'Content-Type':'text/plain;charset=utf-8'
 74     });
 75     res.end('404,page not found');
 76 }
 77 
 78 
 79 function readNewsData(callback){
 80     fs.readFile(path.join(__dirname,'data','data1.json'),'utf8',function(err,data){
 81         if(err&&err.code!=='ENOENT'){
 82             throw err;
 83         }
 84 
 85         var list_news=JSON.parse(data||'[]');
 86         //通过回调函数callback()将读取到的数据list,传递出去
 87         callback(list_news);
 88     });
 89 }
 90 
 91 function writeNewsData(data,callback){
 92     fs.writeFile(path.join(__dirname,'data','data1.json'),data,function(err){
 93         if(err){
 94             throw err;
 95         }
 96         console.log('ok');
 97     });
 98 
 99         //这里写当写入数据完毕后的操作
100         callback();
101 }
102 
103 function postBodyData(req,callback){
104     
105         var array=[];
106         req.on('data',function(chunk){
107             array.push(chunk);
108             //
109         });
110 
111         req.on('end',function(){
112             var postBody=Buffer.concat(array);
113             postBody=postBody.toString('utf8');
114             
115             postBody=querystring.parse(postBody);
116         
117             callback(postBody);
118         });
119 }
View Code

执行顺序

index.js文件从上往下执行,先加载context,在加载router,由于router文件内要先加载handler,所以handler顺序比router前面点,之后就开始监听9090端口,当有了请求后就执行http内部的代码了。

 

原文地址:https://www.cnblogs.com/ellen-mylife/p/11004837.html