以前寫的新聞部分幾乎全部操做都寫在了一塊兒,此次開始進行模塊化。html
1.提升開發效率,全部操做在一個文件內,不方便團隊操做,模塊化可多人同時操做json
2.當程序出錯,能夠分模塊尋找錯誤數組
3.可使程序不一次性所有展現出來,保留一些操做不可見ide
1.思考,該模塊中要封裝什麼代碼?模塊化
2.思考,這些代碼有用到什麼外部數據?若是用到了該如何傳遞
3.當前模塊對外須要暴露的東西(moudule.eports的值)函數
原代碼:post
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); }); }
模塊一(服務模塊):負責啓動服務
模塊二(擴展模塊):負責擴展req和res對象,爲res和res對象,爲req和res增長如下更方便更好用的API
模塊三(路由模塊):負責路由判斷
模塊四(業務模塊):負責處理具體路由的業務的代碼
ui
代碼:url
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 })
負責擴展req和res對象,爲res和res對象,爲req和res增長如下更方便更好用的API
但願在該模塊作:
1.爲req增長一個query熟悉,該屬性中保存的就是用戶get請求提交過來的數據
-req.query
2.爲req增長一個pathname屬性
-req.pathname
3.爲res增長一個render函數spa
代碼:
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); }); }; };
該模塊負責封裝因此路由判斷代碼
代碼:
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 }
該模塊負責對具體的業務進行處理
代碼:
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 }
執行順序
index.js文件從上往下執行,先加載context,在加載router,因爲router文件內要先加載handler,因此handler順序比router前面點,以後就開始監聽9090端口,當有了請求後就執行http內部的代碼了。