这里编写一个异步转同步的方法。
var coHelper = function (fn, fnThis) {
return function () {
fnThis = fnThis||null;
var args = [].slice.call(arguments);
var pass;
var notick = false;
var arg;
args.push(function () {
// 在回调函数中植入收集逻辑
if (pass) {
pass.apply(null, arguments);
}else{
console.log('warning: no callback');
notick = true;
arg = arguments;
}
});
fn.apply(fnThis, args);
if( notick ) return arg;
return function (fn) {
// 传入一个收集函数
pass = fn;
};
};
};
exports.coHelper = coHelper;
原理先不用深入研究,先学习他怎么用,以后在深入其原理。为方便以后使用,我们把他放入一个util.js文件中保存在util文件夹下。下面通过代码举例如何使用。
为了举一个异步请求的例子,我们在百度地图开放平台找一个接口来请求
http://lbsyun.baidu.com/index.php?title=webapi/place-suggestion-api
参考这个api文档,我们写一个请求方法
var http = require('http');
/**
* params为接口请求的参数,包含地图接口参数q(查询关键词)和region(查询范围)
* done为结果回调
*/
function suggestion(params,done) {
var opt = {
method: "GET",
host: "api.map.baidu.com",
port: 80,
path: "/place/v2/suggestion?ak=7cBxGEGTEGBb7kNOiaBOLAFV&output=json&q=" + encodeURIComponent(params.q)+"®ion="+encodeURIComponent(params.region)
};
var request = http.request(opt, function(serverFeedback) {
if(serverFeedback.statusCode == 200) {
var body = "";
serverFeedback.on('data', function(data) {
body += data;
})
.on('end', function() {
done(null, body)
});
} else {
done('error');
}
});
request.end();
}
为将此异步方法转换为同步方法,我们对其用上面写的coHelper 进行转换
var myUtil=require('../util/util');
var suggestion_g = myUtil.coHelper(suggestion);
function * search_poi(params) {
var ret=yield suggestion_g(params)
return ret;
}
exports.search_poi = search_poi;
exports表示公开该方法,相当于其他语言中的public
将以上代码保存为/logic目录下的index.js文件
请求此方法需使用
var index=require('./logic/index');
index.search_poi(params)
加上入口的接口地址为
app.get('/poi/:q/:region',function(req,res){
co(function *(){
var result = yield * index.search_poi( req.params);
res.send(result);
});
});
以上代码保存后运行,浏览器请求 http://www.goodboy.ren:3000/poi/创业路/深圳
可正常获取到数据,结果如下:
{ "status":0, "message":"ok", "result":[ { "name":"创业路-道路", "location":{ "lat":22.517937, "lng":113.950797 }, "uid":"b2acab100e275909100daa9a", "city":"深圳市", "district":"南山区", "business":"", "cityid":"340" }, { "name":"创业路-道路", "location":{ "lat":22.664569, "lng":114.033191 }, "uid":"98ebb3d77101d6ad38e4a69a", "city":"深圳市", "district":"宝安区", "business":"", "cityid":"340" }, { "name":"现代城华庭", "location":{ "lat":22.523027, "lng":113.930763 }, "uid":"631c4157ff354f6030f71dae", "city":"深圳市", "district":"南山区", "business":"", "cityid":"340" }, { "name":"创业路-道路", "location":{ "lat":22.571835, "lng":114.101159 }, "uid":"1f97e077b905a6d4760269dd", "city":"深圳市", "district":"福田区", "business":"", "cityid":"340" }, { "name":"创业路东-公交车站", "location":{ "lat":22.520294, "lng":113.940094 }, "uid":"5102e2d81e013d2000ff2d6b", "city":"深圳市", "district":"南山区", "business":"", "cityid":"340" }, { "name":"中兴工业城", "location":{ "lat":22.522671, "lng":113.929815 }, "uid":"061502a7af3dd8df1b94c64c", "city":"深圳市", "district":"南山区", "business":"", "cityid":"340" }, { "name":"创业路/南光路(路口)", "location":{ "lat":22.522048, "lng":113.93125 }, "uid":"fa7da3e83d6d446342d63e73", "city":"深圳市", "district":"南山区", "business":"", "cityid":"340" }, { "name":"创业路立交桥", "location":{ "lat":22.58417, "lng":113.921686 }, "uid":"a1c66cd1fd278af2db131858", "city":"深圳市", "district":"宝安区", "business":"", "cityid":"340" }, { "name":"创业路/石龙路(路口)", "location":{ "lat":22.703594, "lng":113.976765 }, "uid":"550fd5f91aafc678931fc903", "city":"深圳市", "district":"宝安区", "business":"", "cityid":"340" }, { "name":"木屋烧烤(创业路店)", "location":{ "lat":22.522042, "lng":113.930981 }, "uid":"5ef33a190cd32adf0bccdd7d", "city":"深圳市", "district":"南山区", "business":"", "cityid":"340" } ] }
对以上app的接口请求回调,我们可以对齐封装一下,保存为/util/websvr.js 代码如下
var co=require('co');
function handleReq(path,func_g,app){
app.get(path,function(req,res){
co(function *(){
var result = yield * func_g( req.params);
res.send(result);
});
});
}
exports.handleReq=handleReq;
这样app.js中的请求可改为
var index=require('./logic/index');
var websvr=require('./util/websvr')
//地址位置模糊搜索 q关键词 region搜索城市
websvr.handleReq("/poi/:q/:region",index.search_poi,app);
这样简化了app.js的代码接口,看起来一目了然。
当我们需要增加其他接口时只需要添加以下方法,然后在路由js中实现functionName对应的方法逻辑即可。
websvr.handleReq(path,functionName,app)
总结步骤:
1.在路由js文件中编写异步方法 function1(params,done)方法
2.将其转换为同步方法var function1_g = myUtil.coHelper(function1);
3.在接口逻辑函数function1_logic(params)中调用var result = yield * function1_g(params);获取异步请求结果,并对其进行处理,多个异步请求按顺序逻辑编写即可。同步逻辑同样写在该函数中。
4.引入var websvr=require(‘./util/websvr’),调用websvr.handleReq(path,function1_logic,app)