简体   繁体   English

避免在客户端上使用多个流星方法调用发生回调地狱

[英]Avoiding Callback Hell with Multiple Meteor Method calls on Client

I have multiple Meteor.calls, where each methods depends on the response of another Meteor method. 我有多个Meteor.calls,其中每个方法取决于另一个Meteor方法的响应。

Client 客户

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);
                    }
                })
            }
        });
    }
});

From Meteor's documentation I know 从流星的文档我知道

"Methods called on the client run asynchronously, so you need to pass a callback in order to observe the result of the call." “在客户端上调用的方法是异步运行的,因此您需要传递回调以观察调用结果。”

I know I can create yet another Meteor Method on the server to execute methods 'methodOne', 'MethodTwo', 'MethodThree' wrapped using Meteor.async, or sequentially without the callback all together. 我知道我可以在服务器上创建另一个Meteor方法来执行使用Meteor.async包装的方法“ methodOne”,“ MethodTwo”,“ MethodThree”,或者依次执行而无需回调。 But I am worried this path will cause my meteor methods to get bloated and entangled, leading to spaghetti code. 但是我担心这条路径会导致我的流星方法肿和纠缠,从而导致意大利面条式代码。 I would rather keep each Meteor method simple with one job to do and find a more elegant way of chaining the calls on the client. 我宁愿通过一项工作使每个Meteor方法保持简单,并找到一种更优雅的方式来链接客户端上的调用。 Any ideas, is there any way to use Promises on the client? 有什么想法,有没有办法在客户端上使用Promises?

Since the other answer suggests RSVP this answer will suggest Bluebird which is actually the fastest promise library when running real benchmarks . 由于另一个答案建议RSVP,因此该答案将建议Bluebird ,它实际上是运行真实基准测试时最快的Promise库。 Rather than a micro benchmark that does not really measure anything meaningful. 而不是一个 基准测试 ,它不能真正衡量任何有意义的东西。 Anyway, I'm not picking it for performance, I'm picking it here because it's also the easiest to use and the one with the best debuggability. 无论如何,我不是为了性能而选择它,而是在这里选择它,因为它也是最易于使用和可调试性最好的一种。

Unlike the other answer, this one also does not suppress errors and the cost of making the function return a promise is marginal since no promise constructor is called. 与其他答案不同,该答案也不会抑制错误,并且由于没有调用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); 
});

EDIT: You're probably better off looking at @Benjamin Gruenbaum answer, which not only results in better performance, but also provides much more concise code. 编辑:您最好查看@Benjamin Gruenbaum的答案,这不仅可以带来更好的性能,而且还提供了更简洁的代码。

Promises - yes there is. 承诺-是的。

I like RSVP very much, why? 我非常喜欢RSVP ,为什么? Simply because it's the fastest one. 仅仅是因为它是最快的。 (quick benchmark: jsperf ). (快速基准测试: jsperf )。

Here's quick re-write of your code: 这是您的代码的快速重写:

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);
});

That's the way to prevent "the ever rightward drift" of your code. 这是防止代码“向右漂移”的方法。

Promises are cool, use them. 承诺很酷,请使用它们。

Your approach on the client results in a lot more round trips between the server and the browser. 您在客户端上使用的方法导致服务器和浏览器之间的往返更多。 I know you indicated that you were worried about spaghetti code on the server and I don't have visibility into your application as you do, but just going by the example you provide, it seems like an ideal place to wrap all three calls on the server and make only one call from the client, IMHO. 我知道您表示您担心服务器上的意大利面条代码,并且无法像您那样看到应用程序,但是仅按照您提供的示例进行操作,这似乎是将所有三个调用包装在服务器上的理想位置服务器,并且只能从客户端IMHO拨打一个电话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM