【问题标题】:I can't call Accounts.findUserByEmail() server-side via Meteor.call我无法通过 Meteor.call 调用 Accounts.findUserByEmail() 服务器端
【发布时间】:2017-04-22 22:14:12
【问题描述】:

我只是想通过特定电子邮件验证帐户是否存在,但我了解到 Accounts.findUserByEmail() 仅适用于服务器端。

似乎反复建议的方法是定义一个Meteor.method() 并在那里完成所有工作。不幸的是,我显然不知道自己在做什么,因为我遇到了其他人从未遇到过的错误。

component.js:

Meteor.call('confirm', email);

methods.js:

Meteor.methods({
  'confirm': (email) => {
    if (Accounts.findUserByEmail(email)) {
      return;
    }
  }
});

我得到的只是这个错误:

Exception while simulating the effect of invoking 'confirm' TypeError: Accounts.findUserByEmail is not a function

我是否完全误解了 Meteor.methods + Meteor.call 的动态?它实际上不是服务器端的吗??

目前使用 Meteor 包,accounts-password@1.3.3

【问题讨论】:

    标签: javascript meteor


    【解决方案1】:

    如果您的客户端代码包含方法定义,它会被视为存根,这意味着它以提供“乐观 UI”的特殊模式运行,并且一旦实际的服务器方法返回,它对数据的影响就会撤消它对客户端的响应。

    为客户端和服务器实现不同版本的(至少其中一些)方法可能是值得的,并避免将其中一些完全包含在客户端上。

    如果您选择在客户端和服务器上使用相同的功能,则有Meteor.isServerMeteor.isClientthis.isSimulation(后者专门用于方法),它们允许您执行一些仅在客户端/服务器上阻止。

    请注意,您的问题中的代码没有按照您的预期进行,并且您没有检查方法参数。

    对于这个特定的用例,您可能应该只在服务器上实现该方法(只是不要在您的客户端构建中导入其代码):

    Meteor.methods({
      isEmailInSystem(email) {
        check(email, String);
        return !!Accounts.findUserByEmail(email);
      }
    });
    

    您可以在The Meteor Guide 中阅读有关方法生命周期的更多信息。

    来自指南(要点,省略了一些细节):

    1. 方法模拟在客户端运行 - 如果我们在客户端和服务器代码中定义此方法,所有方法都应如此,则在调用它的客户端中执行方法模拟。

      客户端进入一种特殊模式,在该模式中它跟踪对客户端集合所做的所有更改,以便以后可以回滚。完成此步骤后,您的应用用户会立即看到他们的 UI 更新为客户端数据库的新内容,但服务器尚未收到任何数据。

    2. 方法 DDP 消息发送到服务器
    3. 方法在服务器上运行
    4. 返回值发送给客户端
    5. 任何受该方法影响的 DDP 出版物都会更新
    6. updated 消息发送到客户端,数据替换为服务器结果,方法回调触发
      在将相关数据更新发送到正确的客户端后,服务器会发回 Method 生命周期中的最后一条消息——带有相关 Method ID 的 DDP 更新消息。客户端回滚步骤 1 中方法模拟中对客户端数据所做的任何更改,并将其替换为步骤 5 中从服务器发送的实际更改。

      最后,传递给 Meteor.call 的回调实际上会以第 4 步的返回值触发。重要的是回调要等到客户端是最新的,以便您的方法回调可以假定客户端状态反映了任何更改在方法内部完成。

    【讨论】:

    • 哦酷,这是我第一次读到关于this.isSimulation!非常感谢您的回答。
    【解决方案2】:

    Meteor 也通过运行方法的“存根”来模拟前端的方法调用。这个想法是为了获得更好的用户体验,因为 UI 在服务器响应之前立即更新。但是,这也意味着如果您在 Meteor 方法中运行仅服务器代码,则必须确保代码仅在服务器上运行:

    Meteor.methods({
      'confirm': (email) => {
        if (Meteor.isServer && Accounts.findUserByEmail(email)) {
          return;
        }
      }
    });
    

    或者,您可以将上述方法定义放在仅在服务器上加载的文件中,就像/server-目录中的任何文件或(推荐)将/imports 中的任何文件放在仅include 的文件中一样d 通过服务器代码。那么你应该不需要单独使用Meteor.isServer

    【讨论】:

    • 天哪,非常感谢!我很惭愧地承认,在/server 之外执行时我完全忘记了Meteor.isServer!你是英雄。现在等待 2 分钟选择您的答案作为正确答案。
    猜你喜欢
    • 2013-12-21
    • 2010-10-27
    • 1970-01-01
    • 2011-04-28
    • 2016-11-12
    • 2016-07-27
    • 2013-02-13
    • 2012-03-17
    • 1970-01-01
    相关资源
    最近更新 更多