通过在客户端上调用多个 Meteor 方法避免回调地狱
Avoiding Callback Hell with Multiple Meteor Method calls on Client
我有多个 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 的文档中了解到
"Methods called on the client run asynchronously, so you need to pass a callback in order to observe the result of the call."
我知道我可以在服务器上创建另一个 Meteor Method 来执行方法 'methodOne'、'MethodTwo'、'MethodThree' 使用 Meteor.async 包装,或者在没有回调的情况下顺序执行全部一起。但我担心这条路径会导致我的流星方法变得臃肿和纠缠,导致意大利面条代码。我宁愿通过一项工作来保持每个 Meteor 方法的简单性,并找到一种更优雅的方式来链接客户端上的调用。任何想法,有没有办法在客户端使用 Promises?
编辑:您最好看看@Benjamin Gruenbaum 的回答,这不仅会带来更好的性能,还会提供更简洁的代码。
承诺 - 是的。
我喜欢RSVP very much, why? Simply because it's the fastest one. (quick benchmark: 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);
});
这就是防止 "the ever rightward drift" 代码的方法。
Promise 很酷,使用它们。
由于其他答案建议 RSVP,此答案将建议 Bluebird which is actually the fastest promise library when running real benchmarks. Rather than a micro benchmark 并没有真正衡量任何有意义的东西。无论如何,我不是为了性能而选择它,我在这里选择它是因为它也是最容易使用且具有最佳可调试性的。
与其他答案不同,这个答案也不会抑制错误,并且使函数 return 成为承诺的成本是微不足道的,因为没有调用承诺构造函数。
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);
});
您在客户端的方法导致服务器和浏览器之间的往返次数增加很多。我知道您表示您担心服务器上的意大利面条代码,而且我无法像您一样了解您的应用程序,但仅按照您提供的示例,它似乎是将所有三个调用包装在服务器,只从客户端拨打一个电话,恕我直言。
我有多个 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 的文档中了解到
"Methods called on the client run asynchronously, so you need to pass a callback in order to observe the result of the call."
我知道我可以在服务器上创建另一个 Meteor Method 来执行方法 'methodOne'、'MethodTwo'、'MethodThree' 使用 Meteor.async 包装,或者在没有回调的情况下顺序执行全部一起。但我担心这条路径会导致我的流星方法变得臃肿和纠缠,导致意大利面条代码。我宁愿通过一项工作来保持每个 Meteor 方法的简单性,并找到一种更优雅的方式来链接客户端上的调用。任何想法,有没有办法在客户端使用 Promises?
编辑:您最好看看@Benjamin Gruenbaum 的回答,这不仅会带来更好的性能,还会提供更简洁的代码。
承诺 - 是的。
我喜欢RSVP very much, why? Simply because it's the fastest one. (quick benchmark: 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);
});
这就是防止 "the ever rightward drift" 代码的方法。
Promise 很酷,使用它们。
由于其他答案建议 RSVP,此答案将建议 Bluebird which is actually the fastest promise library when running real benchmarks. Rather than a micro benchmark 并没有真正衡量任何有意义的东西。无论如何,我不是为了性能而选择它,我在这里选择它是因为它也是最容易使用且具有最佳可调试性的。
与其他答案不同,这个答案也不会抑制错误,并且使函数 return 成为承诺的成本是微不足道的,因为没有调用承诺构造函数。
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);
});
您在客户端的方法导致服务器和浏览器之间的往返次数增加很多。我知道您表示您担心服务器上的意大利面条代码,而且我无法像您一样了解您的应用程序,但仅按照您提供的示例,它似乎是将所有三个调用包装在服务器,只从客户端拨打一个电话,恕我直言。