Meteor collection empty on client side - meteor

I am having an issue with a collection.
It is empty only on the client side. See the following which has been stripped back:
MyCollection = new Meteor.Collection("mycollection");
if (Meteor.isServer) {
var result = MyCollection.find({name: 'MyName'}, {limit: 25}).fetch();
console.log(result);
}
if (Meteor.isClient) {
var result = MyCollection.find({name: 'MyName'}, {limit: 25}).fetch();
console.log(result);
}
I can see the result correct from the server code but not the client. What am i missing?

Assuming you haven't removed autopublish or you're correctly publishing and subscribing, you're probably running the client code before it has received the data from the server. Try this:
if (Meteor.isClient) {
Deps.autorun(function() {
var result = MyCollection.find({name: 'MyName'}, {limit: 25}).fetch();
console.log(result);
});
}
You may get one empty result logged on the client, shortly followed by the correct result (after the client receives the data and reruns the autorun function).

Related

Collection subscription but no documents to client

This Meteor code gives full records to the client for one of the collections but the client browser gives:
MyCol.findOne({});
undefined
I also have a server side code which inserts documents into the collection and mongo terminal verifies documents exist.
Any idea why? Thanks
//app.lib.js
MyCol = new Mongo.Collection('myCol');
//server
Meteor.publish('myCol', function() {
return MyCol.find({});
});
//client main.js
Meteor.subscribe('myCol');
Template.checks.helpers({
'values': function() {
return MyCol.find({}); // no documents found,
}
});

Different userId get same document with server publish this.userId

With autopublish package is removed, While this Meteor code is running, a different userId has been confirmed on 2 different browsers consoles Meteor.userId();
But when a string is typed in the inputText of one of them, and a collection.insert is done, the other shows the same string.
I thought that this.userId was good enough for the server to publish only the documents that belongs to each of the different clients simultaneously.
Why is this happening and how to fix it? Thanks
Server
Meteor.publish('displayCol', function () {
return DisplayCol.find({userId: this.userId});
});
DisplayCol.before.insert(function (userId, doc) {
doc.userId = userId;
});
Client
Template.index.helpers({
taskInputs: function () {
var ready = Meteor.subscribe('displayCol').ready();
var data = DisplayCol.find({});
return {items: data, ready: ready};
}
});
Do you have autopublish still installed? If so, both clients will get everything automatically. Remove it with 'meteor remove autopublish'
You can also add the {userId: Meteor.userId()} condition on the client side.

Meteor async call to Instagram API not returning on client side. Returns on server side

Server side:
Meteor.methods({
getFromInstagram: function(){
console.log("called!");
Future = Npm.require('fibers/future');
var myFuture = new Future();
var url = "https://api.instagram.com/v1/media/popular?access_token=[ACCESSTOKEN]";
Meteor.http.get(url, function(error, results){
if(error){
myFuture.throw(error);
} else {
myFuture.return(results);
}
});
console.log( myFuture.wait() );
return myFuture.wait();
}
});
Client side:
instagramContent = Meteor.call("getFromInstagram");
console.log(instagramContent);
The server side console log works and returns an object.
The client side console log in Chrome console returns undefined. What am I overlooking?
Client-side will always be async.
Try something like:
instagramContent = Meteor.call("getFromInstagram", function (error, result) {
console.log(result);
});
From the documentation (http://docs.meteor.com/#meteor_call):
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn't have fibers, so there is not actually any way it can block on the remote execution of a method.

Client Side Asynchronous Call in Meteor?

I have a Meteor client-side asynchronous call that I can't seem to get a return value from. I know I can't use futures on the client-side, so I'm stuck.
And since the Meteor.call() is from the client-side, it has to be asynchronous. It looks like this:
Meteor.call('DirList', path, function(error, result) {
console.log(result);
});
The console.log() works fine, but how do I get the result back into the surrounding function?
Bob
You can store the result in a Session variable and then do the logic with the variable inside a Deps.autorun context. Like:
Meteor.call('DirList', path, function(error, result) { Session.set('result', result); });
Deps.autorun(function (c) {
var result = Session.get('result');
if (!result) return;
c.stop();
alert(result);
});

How to get current user in custom route?

As per this answer I created my own route so that I could handle file uploads. Here's what I've got:
var router = Connect.middleware.router(function(route) {
route.post('/upload', function(req, res) {
var filename = req.headers['x-filename'];
var path = Path.join('.uploads', filename);
var writeStream = FileSystem.createWriteStream(path);
writeStream.on('error', function(e) {
console.error(e);
res.writeHead(500);
res.end();
}).on('close', function() {
Fiber(function() {
console.log(Meteor.user());
}).run();
res.writeHead(200);
res.end();
});
req.pipe(writeStream);
});
});
app.use(router);
This works great for uploading files, but when I try to acess Meteor.user() it gives me:
app/server/main.js:24
}).run();
^
Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
at Object.Meteor.userId (app/packages/accounts-base/accounts_server.js:95:13)
at Object.Meteor.user (app/packages/accounts-base/accounts_server.js:100:25)
at app/server/main.js:23:36
Exited with code: 1
I can't see anything in the req object that might help me out.
Is there any way to get access to the user object?
For the time being, I'm getting the user ID client side and passing it along through the headers which I then use to look up server side:
route.post('/upload', function(req, res) {
Fiber(function() {
var userId = req.headers['x-userid'];
var user = Meteor.users.findOne({_id:userId});
if(user) {
...
} else {
res.writeHead(403,'User not logged in');
res.end();
}
}).run();
});
I don't like this because it's not at all secure. It would be easy to upload something under a different user's account.
Edit: Nevermind. The very act of calling Meteor.users.findOne({_id:userId}); somehow breaks the upload stream. Every file gets corrupt as soon as I put that in; they upload up to about 700 KB and then just stop and close the connection without error.
If it's still valid question.
The problem is that there is no way how to get Meteor.user() in this part of code.
But you can always reach Meteor.userId .. and it's not null if user is logged in .. so you can upload only for logged user. (if req.headers['x-userid'] == Meteor.userId)
The very act of calling Meteor.users.findOne({_id:userId}); somehow
breaks the upload stream.
Because it's reactive part.. so every time if Meteor.users collection is updated this part of code is executed again.
So if you can use only Meteor.userId (which is changed only if user is logged in/out) it should work fine.
I've run into this quite a few times, and it's frustrating. I don't think you can make Meteor.userId() calls from inside a fiber. I usually do a var userId = Meteor.userId(); before I call the fiber, and then reference that variable instead.

Resources