To boil down this issue to the basic problem and a minimum of code, I've created a plain new meteor app, added the accounts-password
package and added the following code snippet. There's a test user in my database.
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');
});
}
As you can see, within the publication this.userId
contains the correct userId. But within the Meteor Method testMethod
both this.userId
and Meteor.userId()
are returning null
.
Is this a meteor bug or is this approach wrong?
This is the expected behavior. It is because you are calling the method from the server. There is no user on the server hence the userId on the method invocation obejct ( this
) is null
. Try calling it from the client when you are logged in.
It is because you don't return a response from the server to your client side. This is how you do it:
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()
},
and your call in the client side :
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)
}
});
The Meteor.userId()
works perfectly in methods or client side, out of the box.
Additionally, publish can only return a cursor to the client side as far as I remember. You can't even return an object you find with findOne()
.
EDIT :
You are calling a method from the server publication without passing any arguements. If you call a method from the client side, from a user account, it won't come back as null or even though I believe it is wrong, it might also work if you pass this.userId as an arguement to your current .call()
in your publish but it will still not give you Meteor.userId() in the method. It will return you the arguement/id you pass from the publish.
How about this?
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');
});
}
In methods,replace
console.log('test2:', this.userId); // => null
console.log('test3:', Meteor.userId()); // => null
With
if(Meteor.user) //USE THIS!
{
console.log('test2:', Meteor.userId()); // => null
console.log('test3:', Meteor.userId()); // => null
}
this.userid won't work in methods. However, using Meteor.userId return the id of the user who invoked the method call.
After lots of discussions and some answers, it seems like Meteor Methods are not intended to be called from the server side and the userId is simply not available if not called from the client side. Despite this is not helpful at all and a counter intuitive behavior of the framework, it's the way Meteor works.
However there's a package called meteor-user-extra
( https://github.com/peerlibrary/meteor-user-extra ) which makes Meteor.userId()
work also inside the publish endpoint functions and solved my problem.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.