Using Meteor, I'm attempting to understand when to use server-side Meteor.methods()
while still retaining instant UI updates.
使用流星,我试图理解什么时候使用服务器端window .methods(),同时仍然保留即时UI更新。
From Andrew Scala's introductory tutorial, he claims that Meteor.methods()
should be used when you want to update and modify your database documents:
在Andrew Scala的介绍性教程中,他声称当您想要更新和修改数据库文档时,应该使用object .methods():
The idea is that you define all the functions on the server that do dangerous stuff like modify and update data, and then let the client call those functions and get return values like regular functions. The client never sees the implementation and doesn’t personally modify the data. The server does all the work.
其思想是定义服务器上的所有函数,这些函数执行诸如修改和更新数据之类的危险操作,然后让客户端调用这些函数并获得常规函数之类的返回值。客户端永远不会看到实现,也不会亲自修改数据。服务器完成所有工作。
And following this advice, I implemented this in my code:
按照这个建议,我在我的代码中实现了这个:
Server-side:
服务器端:
Meteor.methods({
addMovie: function(data) {
var movie = Movies.insert({name: data});
return movie;
},
...
Client-side:
客户端:
Template.movies.events = ({
'click #add-movie': function(e) {
var name = document.getElementById('movie-name').value;
Meteor.call('addMovie', name);
return false;
},
...
This works, but it's slow. The UI doesn't update instantly like it would if you called Movies.insert()
on the client-side. The docs indicate that, to rectify the problem, you can create stubs on the client-side:
这行得通,但很慢。如果在客户端上调用Movies.insert(), UI不会立即更新。文件显示,为了纠正问题,可以在客户端创建存根:
Calling methods on the client defines stub functions associated with server methods of the same name. You don't have to define a stub for your method if you don't want to. In that case, method calls are just like remote procedure calls in other systems, and you'll have to wait for the results from the server.
调用客户机上的方法定义了与同名的服务器方法相关联的存根函数。如果不想,您不必为方法定义存根。在这种情况下,方法调用就像其他系统中的远程过程调用一样,您必须等待服务器的结果。
But what should these stubs look like? Should it basically look the same as the server-side method? If so, what's the point? I'm looking for a more comprehensive explanation of the use and purpose of Meteor.methods()
, the point/use of stubs, and their implementation.
但是这些存根应该是什么样子的呢?它应该基本上与服务器端方法相同吗?如果是的话,有什么意义呢?我正在寻找一个更全面的说明,说明windows .methods()的用途、存根的用途和实现。
EDIT: David Greenspan has helped clarify the use of Meteor.methods() and stubs on meteor-talk.
编辑:David Greenspan帮助澄清了流星。methods()和存根在流星交谈中的使用。
4 个解决方案
#1
19
here's another example.
这是另一个例子。
say you're writing a bingo game and you click the button to call "house!".. in the click event you might call a Method, e.g.
假设你正在写一个宾果游戏,你点击这个按钮就可以调用“house!”在单击事件中,您可以调用一个方法,例如。
Method.call("callHouse");
this will invoke the server method:
这将调用服务器方法:
// on the server
Meteor.methods({
callHouse: function () {
if (currentGame.isInProgress) {
currentGame.winner = this.userId;
currentGame.end();
}
}
});
if you are the first to call "house", the method will mark you as the winner.. however, let's pretend the method is extremely slow and your client app is waiting.. you're 99% sure the server will confirm you are the winner - you just want to update the user's screen without the wait.. in this case implement a client-side stub:
如果你是第一个叫“house”的人,这个方法会把你标记为胜利者。然而,让我们假设这个方法非常缓慢,你的客户端应用程序正在等待。你99%确定服务器会确认你是赢家-你只是想更新用户的屏幕而不需要等待。在这种情况下,实现客户端存根:
// on the client
Meteor.methods({
callHouse: function () {
currentGame.winner = Meteor.userId();
// add any other side-effects you expect to occur here
}
});
when the server result returns, if the data returned is different to what you set in the stub, it will correct it and refresh the screen accordingly.
当服务器结果返回时,如果返回的数据与您在存根中设置的数据不同,它将对其进行更正并相应地刷新屏幕。
#2
12
In short :
简而言之:
Define some methods (Meteor.methods) in the files pushed to the sever that will do actual work on the server, define some methods (Meteor.methods) in the files pushed to the client to get an 'instant' behavior on the client (such as a loading indicator) until the server pushes the resulting changes back to the client
定义一些方法(Meteor.methods)文件推到服务器,在服务器上做实际工作,定义一些方法(Meteor.methods)文件推到客户端得到一个“即时”行为在客户端(如加载指标),直到服务器将由此改变回客户机
Here's David's original post :
以下是大卫的原帖:
Hi Ben,
嗨,本,
In principle, a method can perform completely different actions on the client and server, for example showing a loading indicator on the client and talking to a remote API on the server. Calls to Meteor.methods on the client define the client behavior, and calls to Meteor.methods on the server define the server behavior.
原则上,一个方法可以在客户机和服务器上执行完全不同的操作,例如在客户机上显示一个装载指示器,并在服务器上与远程API对话。流星。客户端上的方法定义客户端行为,并调用流星。服务器上的方法定义服务器行为。
For methods that operate on the database, often the same implementation will do for both. The client version affects the client-side database (the browser-side "cache" of documents subscribed to) and the server-side version affects the real database. When the client hears back, it "snaps" to the result of the server-side mutations; the client-side database mutations are discarded (or undone, depending on how you think about it). If a client-side method calls other methods, these secondary calls are not remoted to the server. The server-side version will either call the same methods on the server, or not, as it sees fit.
对于在数据库上操作的方法,通常对这两种方法都使用相同的实现。客户端版本影响客户端数据库(订阅的文档的浏览器端“缓存”),服务器端版本影响真实的数据库。当客户端收到反馈时,它会“快照”到服务器端突变的结果;客户端数据库突变被丢弃(或撤消,取决于您如何考虑它)。如果客户端方法调用其他方法,则不会将这些辅助调用远程到服务器。服务器端版本将在服务器上调用相同的方法,或者不调用相同的方法。
So any client-side method impl you provide is just a "simulation" and doesn't have to be accurate (it may not be able to be). The hope is that you typically get the simulation impl for free because it's the same as the server impl!
因此,您提供的任何客户端方法impl都只是一个“模拟”,并不一定要准确(它可能不能准确)。希望您能够免费获得模拟impl,因为它与服务器impl相同!
Does this answer your question?
这能回答你的问题吗?
-- David
——大卫
#3
3
If you define a method on a file shared by client/server like /collections
wouldn't it be accessible to both and automatically stub?
如果您在客户机/服务器共享的文件上定义一个方法,比如/collections,那么这两个文件不是都可以访问并自动存根吗?
So:
所以:
/collections/houses.js
/收藏/ houses.js
Meteor.methods({
callHouse: function () {
if (currentGame.isInProgress) {
currentGame.winner = this.userId;
currentGame.end();
}
}
});
This will be available to both the client and server. If it doesn't pass, the server will automatically reject the client update/revert it.
客户端和服务器都可以使用它。如果它不通过,服务器将自动拒绝客户端更新/恢复它。
#4
3
As said Daniel you can define a method on a file which not in client or server directories and available on both sides. You can also use isSimulation
boolean value to make additional checking. For example it may looks something like this:
如Daniel所说,您可以在文件上定义一个方法,该方法不在客户端或服务器目录中,并且在两边都可用。您还可以使用isSimulation boolean值进行额外的检查。例如,它可能看起来是这样的:
Meteor.methods({
addMovie: function (movieData) {
if (!this.isSimulation) {
check(movieData, someAdditionaCheckinFunc);
}
Movies.insert(movieData);
}
})
Thus code in the conditional branch will be executed on server only.
因此,条件分支中的代码将只在服务器上执行。
#1
19
here's another example.
这是另一个例子。
say you're writing a bingo game and you click the button to call "house!".. in the click event you might call a Method, e.g.
假设你正在写一个宾果游戏,你点击这个按钮就可以调用“house!”在单击事件中,您可以调用一个方法,例如。
Method.call("callHouse");
this will invoke the server method:
这将调用服务器方法:
// on the server
Meteor.methods({
callHouse: function () {
if (currentGame.isInProgress) {
currentGame.winner = this.userId;
currentGame.end();
}
}
});
if you are the first to call "house", the method will mark you as the winner.. however, let's pretend the method is extremely slow and your client app is waiting.. you're 99% sure the server will confirm you are the winner - you just want to update the user's screen without the wait.. in this case implement a client-side stub:
如果你是第一个叫“house”的人,这个方法会把你标记为胜利者。然而,让我们假设这个方法非常缓慢,你的客户端应用程序正在等待。你99%确定服务器会确认你是赢家-你只是想更新用户的屏幕而不需要等待。在这种情况下,实现客户端存根:
// on the client
Meteor.methods({
callHouse: function () {
currentGame.winner = Meteor.userId();
// add any other side-effects you expect to occur here
}
});
when the server result returns, if the data returned is different to what you set in the stub, it will correct it and refresh the screen accordingly.
当服务器结果返回时,如果返回的数据与您在存根中设置的数据不同,它将对其进行更正并相应地刷新屏幕。
#2
12
In short :
简而言之:
Define some methods (Meteor.methods) in the files pushed to the sever that will do actual work on the server, define some methods (Meteor.methods) in the files pushed to the client to get an 'instant' behavior on the client (such as a loading indicator) until the server pushes the resulting changes back to the client
定义一些方法(Meteor.methods)文件推到服务器,在服务器上做实际工作,定义一些方法(Meteor.methods)文件推到客户端得到一个“即时”行为在客户端(如加载指标),直到服务器将由此改变回客户机
Here's David's original post :
以下是大卫的原帖:
Hi Ben,
嗨,本,
In principle, a method can perform completely different actions on the client and server, for example showing a loading indicator on the client and talking to a remote API on the server. Calls to Meteor.methods on the client define the client behavior, and calls to Meteor.methods on the server define the server behavior.
原则上,一个方法可以在客户机和服务器上执行完全不同的操作,例如在客户机上显示一个装载指示器,并在服务器上与远程API对话。流星。客户端上的方法定义客户端行为,并调用流星。服务器上的方法定义服务器行为。
For methods that operate on the database, often the same implementation will do for both. The client version affects the client-side database (the browser-side "cache" of documents subscribed to) and the server-side version affects the real database. When the client hears back, it "snaps" to the result of the server-side mutations; the client-side database mutations are discarded (or undone, depending on how you think about it). If a client-side method calls other methods, these secondary calls are not remoted to the server. The server-side version will either call the same methods on the server, or not, as it sees fit.
对于在数据库上操作的方法,通常对这两种方法都使用相同的实现。客户端版本影响客户端数据库(订阅的文档的浏览器端“缓存”),服务器端版本影响真实的数据库。当客户端收到反馈时,它会“快照”到服务器端突变的结果;客户端数据库突变被丢弃(或撤消,取决于您如何考虑它)。如果客户端方法调用其他方法,则不会将这些辅助调用远程到服务器。服务器端版本将在服务器上调用相同的方法,或者不调用相同的方法。
So any client-side method impl you provide is just a "simulation" and doesn't have to be accurate (it may not be able to be). The hope is that you typically get the simulation impl for free because it's the same as the server impl!
因此,您提供的任何客户端方法impl都只是一个“模拟”,并不一定要准确(它可能不能准确)。希望您能够免费获得模拟impl,因为它与服务器impl相同!
Does this answer your question?
这能回答你的问题吗?
-- David
——大卫
#3
3
If you define a method on a file shared by client/server like /collections
wouldn't it be accessible to both and automatically stub?
如果您在客户机/服务器共享的文件上定义一个方法,比如/collections,那么这两个文件不是都可以访问并自动存根吗?
So:
所以:
/collections/houses.js
/收藏/ houses.js
Meteor.methods({
callHouse: function () {
if (currentGame.isInProgress) {
currentGame.winner = this.userId;
currentGame.end();
}
}
});
This will be available to both the client and server. If it doesn't pass, the server will automatically reject the client update/revert it.
客户端和服务器都可以使用它。如果它不通过,服务器将自动拒绝客户端更新/恢复它。
#4
3
As said Daniel you can define a method on a file which not in client or server directories and available on both sides. You can also use isSimulation
boolean value to make additional checking. For example it may looks something like this:
如Daniel所说,您可以在文件上定义一个方法,该方法不在客户端或服务器目录中,并且在两边都可用。您还可以使用isSimulation boolean值进行额外的检查。例如,它可能看起来是这样的:
Meteor.methods({
addMovie: function (movieData) {
if (!this.isSimulation) {
check(movieData, someAdditionaCheckinFunc);
}
Movies.insert(movieData);
}
})
Thus code in the conditional branch will be executed on server only.
因此,条件分支中的代码将只在服务器上执行。