我在流星的客户端事件中有两个流星调用,我想要一个接一个地执行。但是当我调试流程时,不按照我希望的方式进行。
client.js
Meteor.call('methodCall',param1,param2,param3,function (error, result) {
if (error)
console.log(error.reason);
Session.set("xyz",result);
});
var abc=Session.get("xyz");
Meteor.call('methodCall',abc,param2,param3,function (error, result) {
if (error)
console.log(error.reason);
console.log("result: "+result);
Session.set("cdf",result);
});
var pqr=Session.get("cdf");
正如您所看到的,这是我想按顺序运行的代码,即一个接一个。但是当我调试代码时,我发现执行的顺序是:
1. Meteor will be called
3. session.get("xyz") return undefined.
4. Meteor will be called
6. session.get("cdf") return undefined.
2. session.set() will have results as value.
5. session.get() will not have any value.
第二个meteor.call()将无法成功执行,因为第一个参数将不会像在步骤2之前执行的步骤3那样具有任何值。那么有什么方法可以实现这一点并等待流星调用完成以执行下一个指令?
答案 0 :(得分:1)
其中一种方法是重新组织你的代码。
Meteor.call('methodCall',param1,param2,param3,function (error, result)
{
if (error) console.log(error.reason);
Session.set("xyz",result);
var abc=Session.get("xyz");
Meteor.call('methodCall',abc,param2,param3,function (error, result)
{
if (error) console.log(error.reason);
console.log("result: "+result);
Session.set("cdf",result);
var pqr=Session.get("cdf");
});
});
答案 1 :(得分:1)
我已经对这种情况的各种选择进行了一些研究,因为这里的其他人也可能已经面对过这种情况。
第一个也是最明显的一个是进行嵌套调用。这意味着在回调中收到结果后调用下一个函数。
// 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
被动地捕获更改。
许多人可能已经发现这种方法是将异步代码构造成同步代码的第一选择。
Fibers(以及使用光纤的wrapAsync)使代码仅看起来同步,但执行的性质仍然是异步的。这与Promises的工作方式相同,或者像async / await一样工作。
在单一环境中优点:功能强大
缺点:不能与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:
在客户端上,如果你没有通过回调而你不在 存根,调用将返回undefined,你将无法得到 返回方法的值。那是因为客户没有 纤维,所以它实际上没有任何方法可以阻挡遥控器 执行方法。
摘要:Meteor.wrapAsync
不得与Meteor.call
一起使用。
您可以为单个服务器方法提供所有参数和逻辑,而不是尝试创建一个同步的流星调用序列,它返回一个保留所有返回值的对象:
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,
}
}
})
这将创建一个顺序执行(通过遵循您在问题中提供的顺序逻辑)并将其所有结果返回到捆绑对象中。
优点:根据需要顺序,一个请求 - 所有结果 缺点:一个需要测试的额外方法,可以在方法之间引入紧密的coupeling,返回对象可能变得庞大而复杂,以便为clinet进行解析 要求:对方法设计有良好的理解
如果我找到其他选项,我会将它们添加到这篇文章中。
答案 2 :(得分:0)
你必须使用诺言,例如未来的纤维
服务器上的
Meteor.methods({
'methodCall': function(params...){
var future = new Future();
try{
your code...
future.return(result)
catch(e){
future.throw(e)
}finally{
return future.wait();
}
},
})
在客户端
Meteor.call('methodCall',params...,(err,res)=>{
if(err){
console.log(err);
}else{
console.log(res);
}
});