【问题标题】:When to use Meteor.methods and utilizing stubs何时使用 Meteor.methods 和使用存根
【发布时间】:2012-08-27 05:42:19
【问题描述】:

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

来自 Andrew Scala 的 introductory tutorial,他声称当您想要更新和修改数据库文档时应该使用 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() 那样立即更新。 docs 表示,为了解决问题,您可以在客户端创建存根:

在客户端调用方法定义了与关联的存根函数 同名的服务器方法。您不必为 如果你不想,你的方法。在这种情况下,方法调用只是 就像其他系统中的远程过程调用一样,你必须等待 从服务器获取结果。

但是这些存根应该是什么样子?它应该基本上看起来与服务器端方法相同吗?如果是这样,有什么意义?我正在寻找对Meteor.methods() 的使用和目的、存根的要点/使用及其实现的更全面的解释。

编辑: David Greenspan 帮助澄清了 meteor-talk 上 Meteor.methods() 和存根的使用。

【问题讨论】:

  • 您对大卫的回答满意吗?如果是这样,请将其作为答案发布并接受。

标签: javascript node.js meteor stubs


【解决方案1】:

这是另一个例子。

假设您正在编写宾果游戏,然后单击按钮调用“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
  }
});

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

【讨论】:

  • 为什么在服务端使用this.userId,在客户端使用Meteor.userId()
  • 我不记得了,几年前我把 Meteor 装箱了
  • 那太糟糕了。 1.0 摇滚!
  • 根据我的经验,在仅服务器的方法调用和发布函数上使用this.userId 以避免错误。另一方面,只要涉及到客户端(除了发布功能之外的任何地方),请使用Meteor.userId()。见stackoverflow.com/questions/17823268/…
  • 这是否意味着在从本地缓存中获取答案时,在后台向服务器方法发送了一个请求?
【解决方案2】:

简而言之:

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

这是大卫的原帖:

嗨,本,

原则上,一个方法可以在 客户端和服务器,例如在 客户端并与服务器上的远程 API 交谈。来电 客户端上的 Meteor.methods 定义客户端行为,并调用 服务器上的 Meteor.methods 定义了服务器的行为。

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

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

这能回答你的问题吗?

-- 大卫

【讨论】:

  • 谢谢杰。一旦我有更多处理存根的经验,我一直想写一个后续答案。我最终可能会这样做,但我现在会接受你的回答。
  • @jay,对客户端和服务器(在客户端和服务器文件夹之外)使用一种方法是否会产生相同的效果?
  • 嗨@securecurve存根仅用于客户端即时更新,一旦服务器执行操作并返回,其结果将被覆盖。例如,如果您有一个 upVote 方法,在您的客户端上,您可以将投票数加 1,然后更新 UI,但与此同时,Meteor 会在服务器上调用相同的方法(可能返回也可能不返回例如,相同的结果取决于其他人是否投票)
  • @jay,我喜欢你给出的例子 :) ... 非常感谢,非常感谢!
【解决方案3】:

如果您在客户端/服务器共享的文件上定义一个方法,例如/collections,这两种方法都可以访问并自动存根吗?

所以:

/collections/houses.js

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

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

【讨论】:

  • 安全吗?因为用户可以访问代码
  • 是的,您为此使用了流星安全规则。
  • @BrunoLemos 一开始我也有这个顾虑,但 Meteor 背后的部分设计原则是它是无处不在的数据库,因此您可以使用相同的方法从客户端和服务器访问您的数据库.客户端是否可以访问代码并不重要,因为无论客户端是什么,服务器端都会始终验证。
  • @DanielFischer, 是否意味着客户端会先从本地缓存中获取答案,同时向服务器发送请求,当服务器响应时会修补客户端的缓存,或者究竟发生了什么?
【解决方案4】:

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

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

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

【讨论】:

    猜你喜欢
    • 2013-03-12
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 2017-03-28
    • 2012-12-29
    • 2021-06-10
    相关资源
    最近更新 更多