1

考虑到这个例子:

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在一个独特的地方。

4

3 回答 3

5

假设 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
于 2014-05-05T06:08:07.597 回答
1

就在这里。您可以将其简化为一个失败或成功的承诺,并安装nextres.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);
}
于 2014-05-04T21:23:38.507 回答
-2

如果我说得对,并且如果您需要做很多嵌套语句,也许您可​​以检查一下。Async 可以帮助您调用行上的各种函数(有很多方法可以使用 Async 来完成它,请参阅其文档进一步)并且您可以将所有语句放在一起。

于 2014-05-04T20:27:03.617 回答