[英]How to transform a callback hell into promise?
考慮以下示例:
app.get('/url/:param', function(req, res, next) {
var param = req.params.param;
method1(param, function(err, model) {
if(err) return next(err);
method2(model, function(err, models) {
if(err) return next(err);
if(models.length > 0) {
method3(mode, models, function(err, models2) {
res.render("index.html", {model: model, models: models, models2: models2});
});
} else {
res.render("index.html", {model: model, models: models});
}
});
});
}
有沒有一種方法可以使用promise簡化此示例? 看起來所有方法都是依賴的,並且具有if(models.length > 0)
類的驗證。此外,我需要將res.render
到一個唯一的位置。
假設Bluebird,利用庫功能並刪除了嵌套:
var api = Promise.promisifyAll({method1:method1,method2:method2:method3:method3});
api.method1Async(req.params.param).then(function(res){
return [method2Async(res),{model:res}];
}).spread(function(res,result){
result.models = res;
if(models.length > 0){
return method3Async(mode,res).then(function(res){
result.models2 = res;
}).return(result);
}
return results;
}).then(function(results){
res.render("index.html",results);
}).catch(next); // also handle render errors
另外,您可以執行類似的嵌套更少的操作:
var api = Promise.promisifyAll({method1:method1,method2:method2:method3:method3});
var p1 = api.method1Async(req.params.param);
var p2 = p1.then(api.method2Async);
var p3 = p2.then(function(models){
if(models.length > 0) return api.method3Async(mode,models);
});
Promise.all([p1,p2,p3]).spread(function(r1,r2,r3){
var results = {model:r1,models:r2};
if(models.length > 0) results.models2 = r3;
res.render("index.html",results);
}).catch(next)
或者,您可以使用Bluebird協程(需要--harmony-generators標志)
var api = Promise.promisifyAll({method1:method1,method2:method2:method3:method3});
Promise.coroutine(function*(){
var model = yield method1Async(req.params.param);
var models = yield method2Async(model);
if(models.length > 0){
var models2 = yield method3Async(mode,models);
}
res.render("index.html",{model:model,models:models,models2:models2});
})().catch(next); // should probably extract to a clear method rather than self invoke
就在這里。 您可以將其簡化為一個失敗或成功的承諾,然后安裝next
和res.render
作為相應的處理程序。 但是,由於結果取決於先前的所有結果,因此金字塔保持最簡單的狀態。 假設Q.js :
app.get('/url/:param', function(req, res, next) {
Q.nfcall(method1, req.params.param).then(function(model) {
return Q.nfcall(method2, model).then(function(models) {
if(models.length > 0)
return Q.nfcall(method3, mode, models).catch(function(err) {
// you're not dealing with errors here
// omit this `.catch()` call if you want to let it reach the `next()`
}).then(function(models2) {
return {model: model, models: models, models2: models2};
});
else
return {model: model, models: models};
}
});
}).done(function(results) {
res.render("index.html", results);
}, next);
}
如果我把你的權利,如果你需要做大量的嵌套語句,也許你可以檢查這個出來。 異步可以幫助您在行上調用各種函數(有很多方法可以使用異步來完成,請參見其文檔),並且可以將所有語句組合在一起。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.