node——含有异步函数的函数封装
在写代码时我们会发现有大量的重复代码,为了使代码更加简洁,我们可以将重复的代码封装为一个可以在多个部分时候用的函数。
之前写的新闻代码中,经常出现的操作有对文件的读取,我们可以将它封装为一个函数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——含有异步函数的函数封装的更多相关文章
- 转: ES6异步编程:Generator 函数的含义与用法
转: ES6异步编程:Generator 函数的含义与用法 异步编程对 JavaScript 语言太重要.JavaScript 只有一根线程,如果没有异步编程,根本没法用,非卡死不可. 以前,异步编程 ...
- node基础06:回调函数
1.Node异步编程 Node.js 异步编程的直接体现就是回调. 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了. 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,No ...
- 转: ES6异步编程:Thunk函数的含义与用法
转: ES6异步编程:Thunk函数的含义与用法 参数的求值策略 Thunk函数早在上个世纪60年代就诞生了. 那时,编程语言刚刚起步,计算机学家还在研究,编译器怎么写比较好.一个争论的焦点是&quo ...
- C#中 多线程执行含有返回值的函数
C# 中,传统的多线程并不支持多线程执行含有返回结果的函数.虽然可以通过制作外壳类来使得返回结果得以保留,但如果一定时间内函数未执行完,简单的外壳类可能就无法满足需求了. class netHelpe ...
- 转: ES6异步编程: co函数库的含义与用法
转: ES6异步编程: co函数库的含义与用法 co 函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于 Generator 函数的自动执行. 比如,有一个 Ge ...
- 6.26学习 异步委托回调函数 VS 多线程 VS 并行处理
描述: 我现在是轮询着构建实例,然后这个实例去执行一个方法,但是执行方法需要大约10s时间,全部轮询下来需要很长时间.所以我现在要更改,头给了我两个方法,1多线程 2异步委托回调函数. 异步委托回调函 ...
- Thinkphp3.2.3框架下封装公共的函数,例如封装CURL函数来获取接口数据
当我们需要在控制层调用相同的封装函数时,写多次相同的函数,显得代码十分的拉杂,不精简: TP框架有一个很好的机制,可以再Common定义一个function.php函数,当我们在控制层调用的时候直接调 ...
- AsyncTask函数化的封装,AsyncTask函数式的调用
AsyncTask在本专栏已经做过详细的解析,但是AsyncTask函数式的调用这个概念对大多数人来说比较陌生.其实本质就是自己封装AsyncTask,让暴露的方法,看不到一点AsyncTask的身影 ...
- js对函数参数的封装
对函数参数的封装 一个原始函数有n个参数,用wrap对函数进行封装,生成一个新的函数,当给它传入参数数量为n的时候,将执行原始函数,否则不执行 //函数封装 function wrap(func){ ...
随机推荐
- centos7 rpm 安装 rabbitMQ 最新版
首先打开官网: http://www.rabbitmq.com/install-rpm.html 先到右侧导航栏来看一下 : 第一个红框是指的在linux中安装,全英文的,乱的一笔,但是静下心来就可以 ...
- Shader渲染动画
一.概述 先看一下Shader类的介绍: /** * Shader is the based class for objects that return horizontal spans of col ...
- 互联网组织的未来:剖析 GitHub 员工的任性之源
转自:http://innolauncher.com/github/ 互联网组织的未来:剖析 GitHub 员工的任性之源 This entry was posted in Blogon 一月 4, ...
- PHP中调用Soap/WebService
关于在PHP中如何调用Soap/WebService的描述,网络上有不少帖子.但是主要讲述了如何用PHP开发服务器端.客户端并加以关联,而很少触及在PHP中调用现成的WebService的情况.在本文 ...
- Project Euler 26 Reciprocal cycles( 分数循环节 )
题意: 单位分数指分子为1的分数.分母为2至10的单位分数的十进制表示如下所示: 1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6 ...
- 编译驱动模块所需的Makefile
目标定义:就是用来定义哪些内容作为模块编译,哪些内容要编译并链接进内核. obj-y += foo.o 表示要由foo.c或者foo.s文件编译得到foo.o并链接进内核: obj-m则表示该文件要作 ...
- 详解Mysql分布式事务XA(跨数据库事务)
详解Mysql分布式事务XA(跨数据库事务) 学习了:http://blog.csdn.net/soonfly/article/details/70677138 mysql执行XA事物的时候,mysq ...
- maven 创建web项目出错
错误的信息: .m2/repository/org/apache/maven/archetypes/maven-archetype-webapp/maven-metadata-central.xml ...
- angularjs1-7,供应商
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- angularjs1-1
<!DOCTYPE html> <html> <body> <header> <meta http-equiv="Content-Typ ...