我已经对这种情况的各种选择进行了一些研究,因为这里的其他人可能也已经面临过这种情况。
选项 A - 客户端中的嵌套调用
第一个也是最明显的一个是进行嵌套调用。这意味着在回调中收到结果后调用下一个函数。
// level 1
Meteor.call('methodCall', param1, param2, param3, function (error, result) {
// level 2
if (error) console.log(error.reason);
Session.set("xyz",result);
Meteor.call('methodCall',result, param2, param3, function (error, result) {
// level 3...
if (error) console.log(error.reason);
console.log("result: "+result);
Session.set("cdf",result);
});
});
优点:经典的 js 方式,不需要花哨的新概念,服务器方法坚持简单的逻辑,而客户端则完成复杂的工作
缺点:丑陋,会引起混乱,有时难以调试
需要: Template.autorun 或 Tracker.autorun 以响应式捕获来自 Session 的更改。
选项 B - 异步包装
许多人可能已经发现此方法是将异步代码结构化为同步代码的第一选择。
Fibers(以及使用 Fibers 的 wrapAsync)使代码仅看起来同步,但执行的性质保持异步。这与 Promises 的工作方式或 async/await 的工作方式相同。
优点:在单一环境中功能强大
缺点:不能与 Meteor.call 一起使用
需要:要运行的光纤
Meteor.call 的问题
但是,您不能使用此功能轻松调用 Meteor 方法。考虑以下代码
const param1 = "param1";
const param2 = "param2";
const param3 = "param3";
const asyncCall = Meteor.wrapAsync(Meteor.call);
const result1 = asyncCall("methodCall", param1, param2, param3);
// result1 will be undefined
为了进一步解释,我将引用documentation:
在客户端,如果你不传递回调并且你不在一个
存根,调用将返回未定义,您将无法获得
方法的返回值。那是因为客户端没有
光纤,所以实际上没有任何方法可以阻止遥控器
方法的执行。
总结:Meteor.wrapAsync不能和Meteor.call一起使用。
选项 C - 以一种方法捆绑
除了尝试创建同步的流星调用序列,您还可以将所有参数和逻辑提供给单个服务器方法,该方法返回一个保留所有返回值的对象:
client.js
const param1 = "param1";
const param2 = "param2";
const param3 = "param3";
Meteor.call('methodCall', param1, param2, param3, function (err, result) {
const xyz = result.xyz;
const cdf = result.cdf;
});
server.js
function _methodCall(p1, p2, p3) {
// ...
return result;
}
Meteor.methods({
'methodCall'(p1, p2, p3) {
const result1 = _methodCall(p1, p2, p3);
const result2 = _methodCall(result1, p2, p3);
return {
xyz: result1,
cdf: result2,
}
}
})
这将创建一个顺序执行(通过遵循您在问题中提供的顺序逻辑)并将其所有结果返回到一个捆绑对象中。
优点:根据需要按顺序排列,一个请求 - 所有结果
缺点:要测试一个额外的方法,可以在方法之间引入紧密耦合,返回对象可能会变得很大且复杂,无法为客户端解析
要求:对方法设计有一定的了解
如果我找到其他选项,我会将它们添加到这篇文章中。