正确使用 Meteor.userId()

Posted

技术标签:

【中文标题】正确使用 Meteor.userId()【英文标题】:correct use of Meteor.userId() 【发布时间】:2017-04-22 21:19:22 【问题描述】:

这个 Meteor 服务器代码尝试在公共方法“sendEmail”中使用 Meteor.userId(),但有时我会收到错误

Error Meteor.userId 只能在方法调用中调用。使用 this.userId

lib = (function () 

  return Object.freeze(
    'sendEmail': function(msg)
      let userId = Meteor.userId(); 
      //do stuff for this user
    ,
    'otherPublicMethod': function()
      //do other things then use sendEmail
      lib.sendEmail();  // <---- Error Meteor.userId can only be invoked in method calls. Use this.userId
    
  );
());

// Now I call sendEmail from any where, or can I?

Meteor.methods(
  'sendEmail': (msg) => 
    lib.sendEmail(msg); // <---- NO error when this is called
  ,
);

如何解决?谢谢

【问题讨论】:

userId()不允许在Publications内使用,但在Methods内使用没有限制。 【参考方案1】:

我将温和地建议您替换您对IIFE 的使用。相反,您可以利用ES16 modules 来定义您的常用函数。

正如您所指出的,Meteor.userId() 在方法调用中可用,但在服务器上的独立函数中不可用。从方法调用中调用此类函数时,我使用的模式是传入 userId(或实际用户)。例如

imports/api/email/server/utils/emailUtils.js:

const SendEmail = function(userId, msg) 
    // do stuff
;

export SendEmail;

imports/api/email/server/emailMethods.js:

import SendEmail from '/imports/api/email/server/utils/emailUtils';

Meteor.methods(
    'sendEmail': (msg) => 
        check(msg, String);
        // other security checks, like user authorization for sending email
        SendEmail(Meteor.userId(), msg);
    ,
);

现在,您有一个可重复使用的 SendEmail 函数,您可以从任何方法调用或发布。此外,通过遵循这种模式,您离创建可测试代码又近了一步。即,测试注入 userId 的函数比模拟“this.userId”或“Meteor.userId()”更容易。

【讨论】:

我喜欢 IIFE 而不是模块的一个原因是我可以调用像 funcName.methName 这样的公共方法,并且知道我在调用哪个方法,即需要编写的 cmets 更少。【参考方案2】:

如果从任何异步方法调用 lib.sendEmail,请确保绑定 Meteor 环境 例如检查下面模拟异步行为的代码

lib = (function () 
    return Object.freeze(
        'sendEmail': function (msg) 
            let userId = Meteor.userId();
            console.log(userId);
            //do stuff for this user
        ,
        'otherPublicMethod': function () 
            //do other things then use sendEmail
            lib.sendEmail();  // <---- Error Meteor.userId can only be invoked in method calls. Use this.userId
        
    );
());

// Now I call sendEmail from any where, or can I?

Meteor.methods(
    'sendEmail': (msg) => 
        //simulate async behaviour + bind environment
        Meteor.setTimeout(Meteor.bindEnvironment(function () 
            lib.sendEmail(msg); // <---- NO error when this is called
        ));
        //output :
        // null - if user has not logged in else
        // actual userId - if user is loggedin

        //simulate async behaviour without binding environment
        Meteor.setTimeout(function () 
            lib.sendEmail(msg); // <---- error when this is called
        );
        //output :
        // Exception in setTimeout callback: Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
    ,
);

【讨论】:

以上是关于正确使用 Meteor.userId()的主要内容,如果未能解决你的问题,请参考以下文章

userId vs Meteor.userId vs Meteor.userId()

为啥 Meteor.user 和 Meteor.userId 不同?

this.userId 在 Meteor.publish 中返回 undefined

Meteor 中的安全方法

Meteor 中的安全方法

PHP PHP机器人为meteo谷歌