利用q解决嵌套回调的问题

来源:互联网 发布:淘宝如何营销 编辑:程序博客网 时间:2024/05/18 00:47

在javascript中要实现串行的流程,很容易遇到嵌套回调的问题

比如在其他语言中,下面的串行代码:

-(void) doSomething{    Database *db = [self connect];    ResultSet *rs = [db query:sql];    HttpResponse *response = [http get:rs];    NSData *data = [db insert:response];    [self log:data];}

在js中就需要写成如下形式:

connect(url, function(err, db){    db.query(sql, function(err, result){        httpRequest(result, function(err, response){            db.insert(response, function(err, result){               log(result);             });        });    });});

可读性比较差。为了解决嵌套回调的问题,一般有3种办法:事件,流程控制库,以及promise模式

node里最常用的流程控制库是async,在另外一篇博客里已经写过了,本文简单总结promise的方式

常用的库是q,地址在:q

个人感觉比async复杂一些,API比较多,示例代码:

var q = require("q");function getResource(){    var deferred = q.defer();    setTimeout(function(){        deferred.reject({message:"fail"});    },2000);    return deferred.promise;}getResource().then(function(result){    console.log(result.message);}, function(err){    console.log(err.message);});

getResource是一个异步方法,用promise模式来写,先通过defer方法得到promise对象,并且将其返回。当异步过程执行完毕以后,如果成功则调用promise对象的resolve方法,失败调用reject方法,都可以自由传参

这个方法的调用者,则调用promise的then()方法,传递success函数和failure函数,分别对应promise的resolve和reject函数

实践中,常常把async和q混合使用,来实现比较复杂的流程:

var async = require("async");var q = require("q");var request = require("request");function getResource(path) {    var deferred = q.defer();    request({        method: 'GET',        uri: path    }, function (error, response, body) {        if (error) {            deferred.reject({                code: -1,                message: "调用失败"            });            return;        }        if (response.statusCode == 200) {            deferred.resolve(body);            return;        }        deferred.reject({            code: -1,            message: body        });    });    return deferred.promise;}function step1(callback){    getResource("http://www.baidu.com").then(function(result){        callback(null, "111");    }, function(err){        callback(result);    });}function step2(callback){    callback(null, "222");}async.series([step1, step2], function(err, results){    console.log(results);// ["111", "222"]});


0 0