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

在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"]

});


你可能感兴趣的:(问题)