在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]; }
connect(url, function(err, db){ db.query(sql, function(err, result){ httpRequest(result, function(err, response){ db.insert(response, function(err, result){ log(result); }); }); }); });
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); });
这个方法的调用者,则调用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"] });