【问题标题】:Meteor: this.userId and Meteor.userId() both are null within a Meteor MethodMeteor:this.userId 和 Meteor.userId() 在 Meteor 方法中都为 null
【发布时间】:2016-08-31 17:23:52
【问题描述】:

为了将这个问题归结为基本问题和最少的代码,我创建了一个简单的新流星应用程序,添加了 accounts-password 包并添加了以下代码 sn-p。我的数据库中有一个测试用户。

Meteor.methods({
    'testMethod': function() {
        console.log('test2:', this.userId); // => null
        console.log('test3:', Meteor.userId()); // => null
    }
});

if (Meteor.isServer) {
    Meteor.publish('testPublication', function() {
        console.log('test1:', this.userId); // => 1c8tHy3zb8vP9E5yb
        Meteor.call('testMethod');
    });
}

if (Meteor.isClient) {
    Meteor.loginWithPassword('test', 'test', function() {
        Meteor.subscribe('testPublication');
    });
}

如您所见,在发布 this.userId 中包含正确的 userId。但是在 Meteor Method testMethod 中,this.userIdMeteor.userId() 都返回 null

这是流星虫还是这种方法错误?

【问题讨论】:

  • 看起来您的方法在您提供的 sn-p 的全局范围内。 this.userId 只在服务器上工作(我相信你知道),这也会导致嵌套的 Meteor.userId() 失败。
  • 发布是在服务器上执行的,根据目前的答案,这实际上是这里的问题。
  • 那是正确的发布 => 服务器,订阅 => 客户端。方法 => 服务器,调用 => 客户端 ||服务器

标签: javascript meteor


【解决方案1】:

这是预期的行为。这是因为您正在从服务器调用该方法。服务器上没有用户,因此方法调用对象 (this) 上的 userId 是 null。登录后尝试从客户端调用它。

【讨论】:

  • 感谢您的回答。然而,这种行为并不直观。有一个用户,应该可以在服务器端与该用户一起工作。我通过写一个天文事件发现了这个问题(见github.com/jagi/meteor-astronomy/issues/488)。如果这是预期的行为,meteor 在服务器端与当前登录用户合作的预期方式是什么?
  • 为什么不简单地将 userId 从出版物传递给方法?
  • 很难看。我期望从一个框架中,它可以为我工作。就像其他所有框架一样。
  • @phortx 老兄,你没抓住重点。可能有 1000 多个用户同时连接到服务器。因此,如果呼叫源自服务器,则无法将呼叫关联到特定用户。看到了吗?
  • @phortx 被设计为从客户端调用的方法,像某种全局函数一样使用它们是不恰当的。
【解决方案2】:

这是因为您没有从服务器向客户端返回响应。这就是你的做法:

methodName: function (arg1, arg2){
    //do something with the arguements, maybe throw an error:
    if(!Meteor.user()){
        //it won't do anything after the error so you don't have to write an else statement
        throw new Meteor.Error('You are not a user!');
    }

    return Meteor.userId()
},

以及您在客户端的调用:

Meteor.call('methodName', arg1, arg2, function(err, res){
    if(err){
        //err is the error you throw in the method
        console.log(err)
    } else {
        //result is what you return from your method
        console.log(res)
    }
});

Meteor.userId() 在方法或客户端中完美运行,开箱即用。

此外,据我所知,发布只能将光标返回到客户端。您甚至无法返回使用 findOne() 找到的对象。

编辑

您正在从服务器发布调用一个方法,而没有传递任何争论。如果您从客户端调用一个方法,从一个用户帐户,它不会返回为 null 或者即使我认为它是错误的,如果您将 this.userId 作为参数传递给您当前的@987654326,它也可能会起作用@ 在您的发布中,但它仍然不会在方法中为您提供 Meteor.userId() 。它将返回您从发布中传递的争论/ID。

【讨论】:

  • 这不是问题。也许你误解了这个问题:) Meteor Method 被调用。问题是 userId 为空。
  • @phortx 你能在浏览器控制台试试吗?不是 this.userId,试试 Meteor.userId()
  • 当然。它按预期返回 userId,就像问题中提到的发布函数一样。
  • 谢谢。正如我在对另一个答案的评论中提到的那样,这非常不直观......但是我在一个更复杂的情况下偶然发现了这个问题:我需要用户的天文学事件。看看github.com/jagi/meteor-astronomy/issues/488 - 你有什么建议吗?感谢您迄今为止的帮助!
  • @phortx 你能简单解释一下你想做什么吗?发布仅属于当前用户的内容?我会写一个例子,因为 pub/sub/methods 很容易使用,AFAIK 不需要任何技巧
【解决方案3】:

这个怎么样?

function testMethod() {
    console.log('test2:', this.userId); // => should be 1c8tHy3zb8vP9E5yb
}

Meteor.methods({
    'testMethod': testMethod
});

if (Meteor.isServer) {
    Meteor.publish('testPublication', function() {
        console.log('test1:', this.userId); // => 1c8tHy3zb8vP9E5yb
        testMethod.call(this);
    });
}

if (Meteor.isClient) {
    Meteor.loginWithPassword('test', 'test', function() {
        Meteor.subscribe('testPublication');
    });
}

【讨论】:

    【解决方案4】:

    在方法中,替换

     console.log('test2:', this.userId); // => null
     console.log('test3:', Meteor.userId()); // => null
    

    if(Meteor.user)    //USE THIS!
     {
     console.log('test2:', Meteor.userId()); // => null
     console.log('test3:', Meteor.userId()); // => null
    
     }
    

    this.userid 在方法中不起作用。但是,使用 Meteor.userId 返回调用方法调用的用户的 id。

    【讨论】:

    • Ehm ...您看到您发布的代码中的行是相同的吗?两者都返回null?两者都包含在我的原始代码中?
    • 如果您看到我们检查用户 ID 存在的 'if' 语句,它不会返回 null。
    • 通过评论使其“更明显”。 //USE THIS
    • 这不会改变任何事情。 Meteor.userId() 仍然是 null
    • 您的用户登录对吗?它是undefinednull
    【解决方案5】:

    经过大量讨论和一些答案,似乎 Meteor 方法不打算从服务器端调用,如果不从客户端调用,用户 ID 根本不可用。尽管这根本没有帮助,而且框架的行为违反直觉,但 Meteor 就是这样工作的。

    但是,有一个名为 meteor-user-extra (https://github.com/peerlibrary/meteor-user-extra) 的包使 Meteor.userId() 也可以在发布端点函数中工作并解决了我的问题。

    【讨论】:

    • 我已经告诉过你如何在没有包的情况下做到这一点......只需将 id 传递给发布内的调用,它应该可以工作,即使它不是你应该做的。发布中的 Meteor.call('methodName', this.userId) 应该可以工作。我已经向您解释了这一点以及为什么它不起作用。
    • 此外,Meteor.userId() 在服务器端方法中工作。只是不在出版物中。
    • 正如我所提到的,在某些情况下(天文事件)是不可能传递 id 的。
    • Meteor 方法非常适合称为服务器端。如果是,connection 就是null。为什么?因为没有!它是从服务器调用的。没有connection。您无法理解的是,如果函数调用源自服务器,则尝试将其与任何 userId 关联是不合逻辑的。它与 Meteor 是一个框架无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    相关资源
    最近更新 更多