使用Meteor,我试图了解何时在保留即时UI更新的同时使用服务器端Meteor.methods()
。
在AndrewScala的入门教程中,他声称当您想要更新和修改数据库文档时,应该使用Meteor.methods()
:
其想法是,您定义服务器上执行危险的事情,比如修改和更新数据,然后让客户端调用这些函数并获得像常规函数一样的返回值。这个客户端从未看到实现,也不会亲自修改数据服务器完成所有的工作。
按照这个建议,我在代码中实现了这个:
服务器端:
Meteor.methods({
addMovie: function(data) {
var movie = Movies.insert({name: data});
return movie;
},
...
客户端:
Template.movies.events = ({
'click #add-movie': function(e) {
var name = document.getElementById('movie-name').value;
Meteor.call('addMovie', name);
return false;
},
...
这很有效,但速度很慢。UI不会像在客户端调用Movies.insert()
那样立即更新。文档指出,为了纠正这个问题,您可以在客户端创建存根:
客户端上的调用方法定义与关联的存根函数相同名称的服务器方法。您不必为如果你不想的话,可以调用你的方法。在这种情况下,方法调用只是就像其他系统中的远程过程调用一样,您将不得不等待以获取来自服务器的结果。
但是这些树桩应该是什么样子呢?它应该与服务器端方法基本相同吗?如果是,那又有什么意义呢?我正在寻找关于Meteor.methods()
的使用和目的、存根的点/使用及其实现的更全面的解释。
编辑:大卫·格林斯潘帮助澄清了Meteor.methods()和stubs在流星谈话中的使用
这里还有另一个例子。
假设你正在写一个宾果游戏,然后点击按钮呼叫"房子!"。。在点击事件中,您可以调用一个方法,例如
Method.call("callHouse");
这将调用服务器方法:
// on the server
Meteor.methods({
callHouse: function () {
if (currentGame.isInProgress) {
currentGame.winner = this.userId;
currentGame.end();
}
}
});
如果你是第一个叫"房子"的,这个方法会把你标记为赢家。。然而,让我们假设这个方法非常慢,并且您的客户端应用程序正在等待。。你有99%的把握服务器会确认你是赢家-你只想更新用户的屏幕而不需要等待。。在这种情况下,实现一个客户端存根:
// on the client
Meteor.methods({
callHouse: function () {
currentGame.winner = Meteor.userId();
// add any other side-effects you expect to occur here
}
});
当服务器结果返回时,如果返回的数据与您在存根中设置的数据不同,它将对其进行更正并相应地刷新屏幕。
简而言之:
在推送到服务器的文件中定义一些将在服务器上进行实际工作的方法(Meteor.methods),在推送到客户端的文件中指定一些方法(Meteor.methods)以在客户端上获得"即时"行为(如加载指示器),直到服务器将结果更改推回到客户端
这是大卫的原创帖子:
嗨,本,
原则上,一种方法可以对客户端和服务器,例如在客户端,并与服务器上的远程API对话。呼叫客户端上的Meteor.methods定义客户端行为,并调用服务器上的Meteor.methods定义服务器行为。
对于在数据库上操作的方法,通常相同实施将对两者都有好处。客户端版本影响客户端数据库(已订阅文档的浏览器端"缓存"to),并且服务器端版本影响真实数据库。当客户端收到回复,它"捕捉"到服务器端的结果突变;客户端数据库突变被丢弃(或未完成,取决于您的想法)。如果客户端方法调用其他方法,这些辅助调用不是远程到服务器服务器端版本将在上调用相同的方法服务器,或者不在它认为合适的范围内。
因此,您提供的任何客户端方法impl都只是一个"模拟"不一定要准确(可能不准确)。希望是你通常可以免费获得模拟impl,因为它是与服务器impl相同!
这能回答你的问题吗?
--David
如果在客户端/服务器共享的文件(如/collections
)上定义一个方法,它不是可以同时访问并自动存根吗?
因此:
/collections/houses.js
Meteor.methods({
callHouse: function () {
if (currentGame.isInProgress) {
currentGame.winner = this.userId;
currentGame.end();
}
}
});
这将对客户端和服务器都可用。如果它没有通过,服务器将自动拒绝客户端更新/恢复它。
正如Daniel所说,您可以在不在客户端或服务器目录中的文件上定义一个方法,该方法在双方都可用。您也可以使用isSimulation
布尔值进行额外的检查。例如,它可能看起来像这样:
Meteor.methods({
addMovie: function (movieData) {
if (!this.isSimulation) {
check(movieData, someAdditionaCheckinFunc);
}
Movies.insert(movieData);
}
})
因此,条件分支中的代码将仅在服务器上执行。