在客户端上使用多个Meteor Method调用避免回调地狱

时间:2015-02-20 16:01:21

标签: javascript asynchronous meteor promise

我有多个Meteor.calls,其中每个方法都取决于另一个Meteor方法的响应。

客户端

Meteor.call('methodOne', function(err, resOne){
    if(!err){
        Meteor.call('methodTwo', resOne, function(err, resTwo){
            if(!err){
                Meteor.call('methodThree', resTwo, function(err, resThree){
                    if(err){
                        console.log(err);
                    }
                })
            }
        });
    }
});

从Meteor的文档我知道

“客户端上调用的方法是异步运行的,因此您需要传递一个回调以观察调用的结果。”

我知道我可以在服务器上创建另一个Meteor方法来执行方法'methodOne','MethodTwo','MethodThree'使用Meteor.async包装,或者顺序没有回调。但是我担心这条路会导致我的流星方法变得臃肿和纠结,导致意大利面条代码。我宁愿保持每个Meteor方法只需要做一个工作,并找到一种更优雅的方式来链接客户端上的调用。任何想法,有没有办法在客户端使用Promise?

3 个答案:

答案 0 :(得分:13)

由于另一个答案建议RSVP,这个答案会建议Bluebird,这是运行real benchmarks时实际上最快的承诺库。而不是真正衡量任何有意义的a micro benchmark。无论如何,我不是为了表现而选择它,我在这里选择它是因为它也是最容易使用的和具有最佳可调试性的那个。

与其他答案不同,这个答案也不会抑制错误,并且由于没有调用promise构造函数,因此使函数返回promise的成本是微不足道的。

var call = Promise.promisify(Meteor.call, Meteor);

var calls = call("methodOne").
            then(call.bind(Meteor, "methodTwo")).
            then(call.bind(Meteor, "methodThree"));

calls.then(function(resThree){
    console.log("Got Response!", resThree);
}).catch(function(err){
    console.log("Got Error", err); 
});

答案 1 :(得分:3)

编辑:你最好不要看@Benjamin Gruenbaum的回答,这不仅会带来更好的性能,还会提供更简洁的代码。

承诺 - 是的。

我非常喜欢RSVP,为什么?仅仅因为它是最快的一个。 (快速基准:jsperf)。

以下是您的代码的快速重写:

var promise = new RSVP.Promise(function(fulfill, reject) {
  Meteor.call('methodOne', '', function(err, resOne) {
    if (!err) {
      return reject(err);
    }
    fulfill(resOne);
  });
});

promise.then(function(resOne) {
  return new RSVP.Promise(function(fulfill, reject) {
    Meteor.call('methodTwo', resOne, function(err, resTwo) {
      if (err) {
        return reject(err);
      }
      fulfill(resTwo);
    });
  });
}).then(function(resTwo) {
  return new RSVP.Promise(function(fulfill, reject) {
    Meteor.call('methodTwo', resTwo, function(err, resThree) {
      if (err) {
        reject(err);
      }
      fulfill(resThree);
    });
  });
}).then(function(resThree) {
  // resThree is available - continue as you like
  console.log(resThree);
}).catch(function(err) {
  console.log(err);
});

这是阻止代码“向右移动”的方法。

承诺很酷,使用它们。

答案 2 :(得分:3)

您在客户端上的方法会导致服务器和浏览器之间的往返次数增加。我知道你表示你担心服务器上的意大利面条代码并且我不能像你一样了解你的应用程序,但只是通过你提供的例子,它似乎是一个理想的地方来包装所有三个电话在服务器上,只从客户端拨打一个电话,恕我直言。