在写代码时咱们会发现有大量的重复代码,为了使代码更加简洁,咱们能够将重复的代码封装为一个能够在多个部分时候用的函数。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多行的代码,就精简到了十多行,而且封装的函数能够在不少地方使用。