在寫代碼時咱們會發現有大量的重複代碼,爲了使代碼更加簡潔,咱們能夠將重複的代碼封裝爲一個能夠在多個部分時候用的函數。html
以前寫的新聞代碼中,常常出現的操做有對文件的讀取,咱們能夠將它封裝爲一個函數readNewsData()json
function readNewsData(){ 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||'[]'); //return list;//在這樣返回值是不正確的,這裏返回的值是fs.readfile返回的值,不是readNewsData函數返回的值 }); return list; }
在讀取文件後返回list,可是由於有fs.readFile,fs.readFile有異步回調數組
當執行readNewsData函數時,先開啓fs.readfile(),在開啓後當即執行下面的return list;根本不會等fs.readfile將文件讀完。瀏覽器
因此對於有異步回調的和函數,咱們不能以return的形式返回值異步
因此:經過回調函數callback()將讀取到的數據list,傳遞出去函數
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); }); }
在引用的時候:原代碼post
else if(urlObj.pathname==='/item'&&req.method==='get'){ fs.readFile(path.join(__dirname,'data','data1.json'),'utf8',function(err,data){ if(err&&err.code!=='ENOENT'){ throw err; } var model=null; var list_news=JSON.parse(data||'[]'); for(var i=0;i<list_news.length;i++) { if(list_news[i].id.toString()===urlObj.query.id) { model=list_news[i]; break; } } if(model) { res.render(path.join(__dirname,'views','details.html'),{item:model}); } else { res.end('no found') } });
如今:網站
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') } }) }
這樣代碼會少一些,而readNewsData(function(list){});裏面的list就是封裝函數裏面callback(list)url
寫入文件函數和上面的方法同樣spa
原代碼:
else if(req.url.startsWith('/add')&&req.method==='post'){ fs.readFile(path.join(__dirname,'data','data1.json'),'utf8',function(err,data){ //由於第一次訪問網站,data1.json文件自己就不存在,因此會有異常 //這種錯誤,咱們不認爲是網站出錯了,因此不須要拋出異常 if(err&&err.code!=='ENOENT'){ throw err; } //若是data沒有讀取到,則data爲空,轉換爲數組 var list_news=JSON.parse(data||'[]'); var array=[]; req.on('data',function(chunk){ //此處的chunk參數,就是瀏覽器本次提交過來的一部分數據 //chunk的數據類型是buffer array.push(chunk); }); //監聽request對象的end事件 //當end事件被觸發時,數據提交完成 req.on('end',function(){ var postBody=Buffer.concat(array); postBody=postBody.toString('utf8'); postBody=querystring.parse(postBody); //把新聞添加到list以前,爲新聞增長一個id postBody.id=list_news.length; //將用戶的push提交到新聞push到List_news中 list_news.push(postBody); fs.writeFile(path.join(__dirname,'data','data1.json'),JSON.stringify(list_news),function(err){ if(err){ throw err; } console.log('ok'); }); res.statusCode=302;//跳轉 res.statusMessage='Found'; res.setHeader('Location','/'); res.end('over'); }); }); }
紅色部分封裝代碼
//封裝一個寫入data1.json的函數 //這裏傳過來的data是轉換爲字符串的數據 function writeNewsData(data,callback){ fs.writeFile(path.join(__dirname,'data','data1.json'),data,function(err){ if(err){ throw err; } console.log('ok'); }); //這裏寫當寫入數據完畢後的操做 callback(); }
修改後:
else if(req.url.startsWith('/add')&&req.method==='post'){ readNewsData(function(list_news){ 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); 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'); }); }); }); }
上面post提交數據還能夠封裝爲一個函數
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); //把用戶post提交過來的返回 callback(postBody); }); }
原來post函數修改後
else if(req.url.startsWith('/add')&&req.method==='post'){ //1.讀取data1.json readNewsData(function(list_news){ //2.讀取用戶post提交的數據 postBodyData(req,function(postBody){ //3.爲用戶提交的新聞增長一個id屬性,而且把新聞對象push到list中 postBody.id=list_news.length; list_news.push(postBody); //將list數組寫入到data1.json中 writeNewsData(JSON.stringify(list_news),function(){ res.statusCode=302; res.statusMessage='Found'; res.setHeader('Location','/'); res.end('over'); }); }); }); }
這樣原來有20多行的代碼,就精簡到了十多行,而且封裝的函數能夠在不少地方使用。