33

使用 Meteor,我试图了解何时使用服务器端Meteor.methods(),同时仍保留即时 UI 更新。

从 Andrew Scala 的介绍性教程中,他声称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() 和流星谈话上的存根的使用。

4

4 回答 4

19

这是另一个例子。

假设您正在编写宾果游戏,然后单击按钮调用“house!”.. 在单击事件中,您可能会调用方法,例如

Method.call("callHouse");

这将调用服务器方法:

// on the server
Meteor.methods({
  callHouse: function () {
    if (currentGame.isInProgress) {
      currentGame.winner = this.userId;
      currentGame.end();
    }
  }
});

如果您是第一个调用“house”的人,该方法会将您标记为获胜者.. 但是,让我们假设该方法非常慢并且您的客户端应用程序正在等待.. 您有 99% 的把握服务器会确认您是获胜者-您只想更新用户的屏幕而无需等待..在这种情况下实现客户端存根:

// on the client
Meteor.methods({
  callHouse: function () {
    currentGame.winner = Meteor.userId();
    // add any other side-effects you expect to occur here
  }
});

当服务器结果返回时,如果返回的数据与你在存根中设置的不同,它会更正它并相应地刷新屏幕。

于 2012-10-30T18:27:36.140 回答
12

简而言之 :

在推送到服务器的文件中定义一些方法(Meteor.methods)将在服务器上执行实际工作,在推送到客户端的文件中定义一些方法(Meteor.methods)以获得客户端上的“即时”行为(例如加载指示器),直到服务器将生成的更改推送回客户端

这是大卫的原始帖子:

嗨,本,

原则上,一种方法可以在客户端和服务器上执行完全不同的操作,例如在客户端上显示加载指示器并与服务器上的远程 API 对话。在客户端调用 Meteor.methods 定义客户端行为,在服务器调用 Meteor.methods 定义服务器行为。

对于在数据库上操作的方法,通常相同的实现将适用于两者。客户端版本影响客户端数据库(订阅文档的浏览器端“缓存”),服务器端版本影响真实数据库。当客户端收到回复时,它会“捕捉”到服务器端突变的结果;客户端数据库突变被丢弃(或撤消,取决于您如何看待它)。如果客户端方法调用其他方法,这些辅助调用不会远程到服务器。服务器端版本将在服务器上调用相同的方法,或者不调用它认为合适的方法。

因此,您提供的任何客户端方法 impl 都只是一个“模拟”,并且不必是准确的(它可能无法准确)。希望您通常免费获得模拟 impl,因为它与服务器 impl 相同!

这回答了你的问题了吗?

- 大卫

于 2012-10-25T04:19:41.627 回答
3

如果您在客户端/服务器共享的文件上定义一个方法,就像/collections它不会被两者访问并自动存根?

所以:

/collections/houses.js

Meteor.methods({
  callHouse: function () {
    if (currentGame.isInProgress) {
      currentGame.winner = this.userId;
      currentGame.end();
    }
  }
});

这对客户端和服务器都可用。如果没有通过,服务器将自动拒绝客户端更新/恢复它。

于 2014-07-21T00:10:52.900 回答
3

正如丹尼尔所说,您可以在文件上定义一个方法,该方法不在客户端或服务器目录中,并且在双方都可用。您还可以使用isSimulation布尔值进行额外检查。例如,它可能看起来像这样:

Meteor.methods({
  addMovie: function (movieData) {
    if (!this.isSimulation) {
      check(movieData, someAdditionaCheckinFunc);
    }
    Movies.insert(movieData);
  }
})

因此条件分支中的代码将仅在服务器上执行。

于 2014-08-12T21:05:22.323 回答