我觉得我做错了,因为我的结果似乎违背了Meteor模拟客户/服务器交互速度的本质。当我使用Meteor.call()
进行任何类型的数据库更新时,应用程序必须等待往返服务器,通常会导致响应缓慢或用户按两次按钮。我只是想确保我正确地做到这一点。这就是我正在做的事情:
客户端:
Template.shot.events({
'change #shot-status-select': function (event, template) {
var new_status = $(event.target).val();
var shot_id = Session.get('current_shot_id');
Meteor.call('setShotStatus', shot_id, new_status, function (error, result) {
if (result) {
feedbackSuccess('Status changed to <b>'+new_status+'</b>');
} else {
feedbackError('Status change failed');
console.log(error);
}
});
},
});
和服务器:
...
'setShotStatus': function(shot_id, status) {
var result = Shots.update({'_id': shot_id}, {$set: {'status': status}});
if (result) {
return true;
} else {
return false;
}
},
答案 0 :(得分:2)
这里有一些事情阻止你的方法被延迟补偿(它完成了到服务器的完整往返)。
首先,如果您在客户端上使用回调执行Meteor.call,它将始终等待来自服务器的结果。不幸的是,您无法同步编写它,因为call
将始终在客户端返回undefined
,并且您需要返回的结果。
如果你真的想要存根的结果,你需要像这样重写它:
var args = [shot_id, new_status];
var result = Meteor.apply('setShotStatus', args, {returnStubValue: true});
if (result)
feedbackSuccess('Status changed to <b>'+new_status+'</b>');
请注意,如果可能出现错误,您应将call
包裹在try
/ catch
中。另请注意,客户端和服务器返回值在一般情况下并不总是匹配,因此请考虑使用此技术。
接下来,您的方法定义需要位于客户端和服务器代码的共享位置(将其放在lib
下面或包中是不错的选择)。如果客户没有方法代码,则无法对其进行模拟。
推荐阅读:
答案 1 :(得分:0)
谢谢大卫。你的回答让我走上了正确的道路,但我认为那里有几个小块似乎在评论中讨论太多了。我发现的主要是:
回到“流星零延迟”承诺的挑战就像将所有“服务器”方法移动到lib
目录一样简单。
从字面上看,没有代码更改。在让客户端和服务器都可以访问这些方法之后,Meteor首先在客户端执行了所有繁重的操作,然后使用服务器结果检查结果。
David的回答说使用回调将始终等待服务器的结果。我发现这部分是正确的,因为它会异步地等待结果。虽然取决于您的方法的可访问性,但它可能是您遇到的客户端的结果,而不是来自服务器的往返。不使用回调将始终返回undefined
,因此result
将无法在给定示例中使用
最后,出于安全原因,我将真正的私有逻辑移动到仅服务器目录。
以下是代码结果:
<强>的客户机/ shot.js 强>
Template.shot.events({
'change #shot-status-select': function (event, template) {
var new_status = $(event.target).val();
var shot_id = Session.get('current_shot_id');
Meteor.call('setShotStatus', shot_id, new_status, function (error, result) {
if (!(result)) {
feedbackError('Status change failed');
console.log(error);
}
});
},
});
<强> LIB / methods.js 强>
Meteor.methods({
'setShotStatus': function(shot_id, status) {
var result = Shots.update({'_id': shot_id}, {$set: {'status': status}});
if (result) {
return true;
} else {
return false;
}
},
});