正确使用Meteor.userId()

时间:2017-04-22 21:19:23

标签: meteor

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

  

错误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
  },
});

如何修复? THX

2 个答案:

答案 0 :(得分:1)

如果从任何异步方法调用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.
    },
});

答案 1 :(得分:0)

我会轻轻地建议您替换IIFE的使用。相反,您可以利用ES16 modules来定义常用功能。

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

进口/ API /电子邮件/服务器/ utils的/ emailUtils.js:

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

export {SendEmail};

进口/ API /电子邮件/服务器/ 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()”更容易。