在写代码时我们会发现有大量的重复代码,为了使代码更加简洁,我们可以将重复的代码封装为一个可以在多个部分时候用的函数。

之前写的新闻代码中,经常出现的操作有对文件的读取,我们可以将它封装为一个函数readNewsData()

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);
});
}

在引用的时候:原代码

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)

写入文件函数和上面的方法一样

原代码:

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=;
res.statusMessage='Found';
res.setHeader('Location','/');
res.end('over'); });
});
}); }

这样原来有20多行的代码,就精简到了十多行,并且封装的函数可以在很多地方使用。

node——含有异步函数的函数封装的更多相关文章

  1. 转: ES6异步编程:Generator 函数的含义与用法

    转: ES6异步编程:Generator 函数的含义与用法 异步编程对 JavaScript 语言太重要.JavaScript 只有一根线程,如果没有异步编程,根本没法用,非卡死不可. 以前,异步编程 ...

  2. node基础06:回调函数

    1.Node异步编程 Node.js 异步编程的直接体现就是回调. 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了. 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,No ...

  3. 转: ES6异步编程:Thunk函数的含义与用法

    转: ES6异步编程:Thunk函数的含义与用法 参数的求值策略 Thunk函数早在上个世纪60年代就诞生了. 那时,编程语言刚刚起步,计算机学家还在研究,编译器怎么写比较好.一个争论的焦点是&quo ...

  4. C#中 多线程执行含有返回值的函数

    C# 中,传统的多线程并不支持多线程执行含有返回结果的函数.虽然可以通过制作外壳类来使得返回结果得以保留,但如果一定时间内函数未执行完,简单的外壳类可能就无法满足需求了. class netHelpe ...

  5. 转: ES6异步编程: co函数库的含义与用法

    转: ES6异步编程: co函数库的含义与用法 co 函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于 Generator 函数的自动执行. 比如,有一个 Ge ...

  6. 6.26学习 异步委托回调函数 VS 多线程 VS 并行处理

    描述: 我现在是轮询着构建实例,然后这个实例去执行一个方法,但是执行方法需要大约10s时间,全部轮询下来需要很长时间.所以我现在要更改,头给了我两个方法,1多线程 2异步委托回调函数. 异步委托回调函 ...

  7. Thinkphp3.2.3框架下封装公共的函数,例如封装CURL函数来获取接口数据

    当我们需要在控制层调用相同的封装函数时,写多次相同的函数,显得代码十分的拉杂,不精简: TP框架有一个很好的机制,可以再Common定义一个function.php函数,当我们在控制层调用的时候直接调 ...

  8. AsyncTask函数化的封装,AsyncTask函数式的调用

    AsyncTask在本专栏已经做过详细的解析,但是AsyncTask函数式的调用这个概念对大多数人来说比较陌生.其实本质就是自己封装AsyncTask,让暴露的方法,看不到一点AsyncTask的身影 ...

  9. js对函数参数的封装

    对函数参数的封装 一个原始函数有n个参数,用wrap对函数进行封装,生成一个新的函数,当给它传入参数数量为n的时候,将执行原始函数,否则不执行 //函数封装 function wrap(func){ ...

随机推荐

  1. Java Spring 两大特色

    0 引言 本文主要描述的是Spring常用的两大特色功能:AOP和IoC容器 1 IoC Spring的IoC:就是常说的“控制反转”,也又叫依赖注入的(DI). 优点:IoC最大的好处就是把对象生成 ...

  2. 记一次vip视频破解过程(爱奇艺 芒果 腾讯 优酷 )

    1. 在爱奇艺或者优酷中拿到视频的url地址.此时拿到的是加密地址(也可以直接在牛巴巴里面搜名字然后开f12跟踪路由) 2.进入牛巴巴vip视频解析网站.粘贴拿到的url.点击解析 3.f12在net ...

  3. Centos 7.2 安装和卸载 MySQL 5.7

    一.背景 闲暇之余在虚拟机安装了 Centos 7.2 系统,按照 <简单安装MySQL(RPM方式)> 这篇文章安装 MySQL ,发现由于包依赖的问题安装失败,于是索性在官网查询相关文 ...

  4. 原生node写一个静态资源服务器

    myanywhere 用原生node做一个简易阉割版的anywhere静态资源服务器,以提升对node与http的理解. 相关知识 es6及es7语法 http的相关网络知识 响应头 缓存相关 压缩相 ...

  5. Codeforces 789A Anastasia and pebbles( 水 )

    链接:传送门 题意:这个人每次都去公园捡石子,她有两个口袋,每个口袋最多装 k 个石子,公园有 n 种石子,每种石子 w[i] 个,询问最少几天能将石子全部捡完 思路:排个序,尽量每天都多装,如果 k ...

  6. BZOJ 3110 [ZJOI2013]K大数查询 (整体二分+线段树)

    和dynamic rankings这道题的思想一样 只不过是把树状数组换成线段树区间修改,求第$K$大的而不是第$K$小的 这道题还有负数,需要离散 #include <vector> # ...

  7. HDU 3849 By Recognizing These Guys, We Find Social Networks Useful

    By Recognizing These Guys, We Find Social Networks Useful Time Limit: 1000ms Memory Limit: 65536KB T ...

  8. 用 query 方法 获得xml 节点的值

    DECLARE @result xml SET @result='<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelo ...

  9. getColor()方法过时的替代方法

    Android SDK 升級到 23 之後,getResource.getColor(R.color.color_name) 過時 使用新加入的方法 ContextCompat.getColor(co ...

  10. 9patch生成图片

    private Bitmap get_ninepatch(int id,int x, int y, Context context){ // id is a resource id for a val ...