node.js学习(九、进一步异步优化)

这里编写一个异步转同步的方法。

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)+"&region="+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)

完整代码git地址 https://github.com/feng12345566/nodejs_study

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值