nodejs+express一个很经典的问题--异步获取数据模板渲染
来源:互联网 发布:电视挂墙高度知乎 编辑:程序博客网 时间:2024/06/01 07:18
前言
很多时候nodejs都会有一些异步操作,譬如,读写文件,譬如,用httprequest来获取后台数据然后渲染,但是由于nodejs的特性,很多时候都是异步的,那么如何解决。
问题代码
/** * 商品分类相关api。 * */var request = require('request');var Settings=require('../settings.js');var fs = require('fs');var sysUtil = require('../util/SystemUtil.js');var logger=sysUtil.Logger;exports.getMenuList=function(callback){ logger.info("访问url:"+Settings.WebApi.ApiHost+Settings.WebApi.IndexMenuApi); var _url=Settings.WebApi.ApiHost+Settings.WebApi.IndexMenuApi; //_url="http://www.baidu.com"; request(_url, function (error, response, body) { if (!error && response.statusCode == 200) { if(callback){ callback(response,body); } } else{ console.log("后台通信端错误。"); } }).pipe(fs.createWriteStream('./test/file1.txt'));};
var express = require('express');var router = express.Router();var Settings=require("../settings");var sysUtil=require("../util/SystemUtil.js");var logger=sysUtil.Logger;var fs=require("fs");/* GET home page. */router.get('/', function(req, res, next) { //console.log("================"); //console.log(Settings); //--获取首页菜单数据。 var CategoryService=require("../service/CategoryService.js"); var _menuList={}; CategoryService.getMenuList(function(res1,body1){ _menuList=JSON.parse(body1); //fs.writeFile("./test/file1.txt",JSON.stringify(_menuList),function(){}); }); res.render('index', { title: 'Express' ,menuList:_menuList});});module.exports = router;
ok,我们会发现,渲染模板的时候,menuList永远为空。。。。
解决方案
一个比较可行的方法是用deffered 、promise方案,当然,request这个也需要用deffered promise封装一下,否则会写死人的。
下面是项目中应用的成熟方案代码,部分:
/** * 该文件是针对request获取及存储数据的封装,当然,包含了promise的帮助。 */var logger = require('../util/logHelper.js').Logger;var fs=require("fs");var Q = require('q');var util=require("../util/util.js");var request = require('request');var Extend=require("util")._extend;var RequestHelper=function(){ this.taskList=[];};RequestHelper.prototype.addTask=function(_opt){ this.taskList.push(_opt);}RequestHelper.prototype.request=function(_opts){ var _deferred= Q.defer(); var _i_settings={ url:"" ,method:"get" ,data:{} ,dataType:"json" ,error:function(error){ } ,success:function(sdata){ } }; _i_settings=Extend(_i_settings,_opts); if(_i_settings.method.toLocaleLowerCase()=="get"){ var _realUrl=util.Json2URL(_i_settings.url,_i_settings.data); logger.info(_realUrl); var req2=request(_realUrl, function (error, response, body) { if (!error && response.statusCode == 200) { var _res=body; try{ if(_i_settings.dataType=="json"){ _res=JSON.parse(_res); } } catch (ex){ var _error_msg="nodejs can not trans this data to JSON format: "+body; logger.error("json translate error:"+_i_settings.url); logger.error(_error_msg); logger.error(body); _deferred.reject(_error_msg); return; } _deferred.resolve(_res);} else{ var _error_msg="request helper error: can not request url:"+_realUrl+""; logger.error(_error_msg); logger.error(body); _deferred.reject(error); } }); } else{ //--post方式。 request.post({ url:_i_settings.url ,form:_i_settings.data },function(err,response,body){ if (!err && response.statusCode == 200) { var _res=body; try{ if(_i_settings.dataType.toLocaleLowerCase()=="json"){ _res=JSON.parse(_res); } } catch (ex){ var _error_msg="nodejs can not trans this data to JSON format: "+body; logger.error("json translate error:"+_i_settings.url); logger.error(_error_msg); logger.error(body); _deferred.reject(_error_msg); return; } _deferred.resolve(_res);} else{ var _error_msg="request helper error: can not request url:"+_i_settings.url+""; logger.error(_error_msg); logger.error(err); logger.error(body); _deferred.reject(err); } }); } var _promise= _deferred.promise; _promise.then(_i_settings.success,_i_settings.error); return _promise;};RequestHelper.prototype.run=function(onDone){ var me=this; var taskList=this.taskList; if(taskList.length<=0){ if(onDone){ onDone(); } return; } var _now_taskReq=[]; for(var i=0;i< this.taskList.length;i++){ var _taskItem={ url:"" ,success:function(parameter){ } ,error:function(parameter){ } ,method:"get" ,data:{} ,dataType:"json" }; Extend(_taskItem,this.taskList[i]); var _promise=me.request(_taskItem); _now_taskReq.push(_promise); } //--检查是不是有多于或等于一个任务。 if(_now_taskReq.length<=0){ var _warning_msg="request helper warning:task list has less than 1 task,do not send any request now."; logger.warn(_warning_msg); if(onDone){ onDone(); } return; } Q.all(_now_taskReq) .spread(function(){}).done(function(){ if(onDone){ onDone(); } }); };module.exports=RequestHelper;
如何使用:
//商品推荐router.get('/recommend',function(req,res,next){ GlobalService.getCommonPageData(req,function(commonData){ //res.send(JSON.stringify(commonData)); var pageData={ list:[] ,ads:[] }; var ajaxHelper=new RequestHepler(); ajaxHelper.addTask({ url:ServerConf.ApiHost+Settings.WebApi.RecommendProductApi ,success:function(data){ var _json=data; pageData.list=_json.rows; } ,error:function(error){ logger.error(error); } }); ajaxHelper.addTask({ url:ServerConf.ApiHost+Settings.WebApi.RecommendProductAdApi ,success:function(data){ var _json=data; pageData.ads=_json.rows; } ,error:function(error){ logger.error(error); } }); ajaxHelper.run(function(){ commonData["pageData"]=pageData; res.render('recommend', commonData); }); });});
原理是加入多个任务队列,然后最后才执行最后的方法。
0 0
- nodejs+express一个很经典的问题--异步获取数据模板渲染
- express 获取数据后渲染
- NodeJS中,Express获取request所传递的数据方式
- Nodejs express获取Ajax(post方式)发送的数据
- NodeJS框架Express的模板视图机制
- nodejs express ejs模板处理get请求,获取参数的几种方式
- nodejs express 获取请求信息的方法
- nodejs模板渲染forEach
- express的多重页面渲染问题
- 关于nodejs express安装不成功的问题
- Nodejs Express下引入本地文件的问题
- js异步获取数据的问题
- nodejs express 加载html模板
- Nodejs express框架之jade模板的学习笔记
- nodejs+express生成的模板引擎jade改为html
- vuejs 数据渲染成功仍然报错的一个问题
- nodejs的express获取get和post传值
- NodeJS的Express框架获取Http请求参数
- matlab实现zbar_scan_y
- OSI/RM 开放系统互联参考模型
- 2.6.3from…import详解
- WWW 服务器(LAMP)搭建
- Paxos和分布式存储系统
- nodejs+express一个很经典的问题--异步获取数据模板渲染
- 实现列表手势向左向右滑动删除条目
- textView表情代码相关
- 2016年c#冒泡排序
- Mybatis之Foreach
- C++的Json解析库:jsoncpp和boost
- Http协议
- C++常用知识列表
- SSL VPN应用