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

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.

Related

meteorjs get data returned from server callback

In meteor im trying to insert a new document by making a Meteor.call from the client. Everything is working ok, except that I want to return the id of create document to the client, so that i can redirect to the proper url.
I have something similar to this (client):
Meteor.call('scenarioCreate', scenarioObj, function(err, response) {
if(err) {
console.warn(err);
return;
}
console.info(response);
});
On server:
Meteor.methods({
'scenarioCreate': function(scenarioObj) {
Scenarios.insert( scenarioObj, function(err, id) {
console.info("new id: "+id);
if (err) {
console.warn(err);
throw new Meteor.Error(404, 'Something went wrong');
}
return id;
});
}
});
From the server side i get the console log "new id: DDaq4aWsGf3fxG7RP", but I should get that same value on the client on the "response" value, but I always get undefined.
Can anybody explain to me why or what I am doing wrong.
Meteor.methods doesn't wait for your callback. Try this:
On server:
Meteor.methods({
'scenarioCreate': function(scenarioObj) {
var newId = Scenarios.insert(scenarioObj);
return newId;
}
});
To catch any error, use try/catch
Note: If you still want to use callback, checkout fibers/future.
Your first error is that you are returning id inside the callback for insert. That doesn't do anything. Then your second is not knowing that methods are synchronously executed. That would mean that you could only use the information available inside the callback using Meteor.wrapAsync. But that's besides the point. The insert function returns the new _id. Meaning you can do this:
Meteor.methods({
'scenarioCreate': function(scenarioObj) {
return Scenarios.insert( scenarioObj );
}
});

Meteor.call and latency compensation

I'm trying to understand why am I getting the error when calling a meteor server method. It works on the server side but it's throwing errors in the browser.
This is my server code in /server/methods.js file:
Meteor.methods({
getTicketSettings: function(){
var getTicketConfig = function(callback){
Assets.getText('ticketCustomizing.json', function(error, res){
if (error)
throw new Meteor.Error({error:'ticket-getCustomizing', reason:'No se pudo recuperar la configuraciĆ³n.'});
else callback && callback(null, JSON.parse(res));
});
}
var syncAssetRetrieve = Meteor.wrapAsync(getTicketConfig);
var result = syncAssetRetrieve();
return result;
},
});
And this is in my client/server code in /lib/initialization.js file:
App.config.tickets.tipos = new Mongo.Collection('tipos');
Meteor.startup(function(){
moment.locale('es');
var ticketSettingsObj = Meteor.call('getTicketSettings');
console.log(ticketSettingsObj);
_.map(ticketSettingsObj.tipos, function(tipo){
App.config.tickets.tipos.insert(tipo);
});
});
When I run my application I have the JSON object logged in the console but the browser is showing this error: Uncaught TypeError: Cannot read property 'tipos' of undefined in my /lib/initialization.js here:
_.map(ticketSettingsObj.tipos, function(tipo){
App.config.tickets.tipos.insert(tipo);
});
Obviously I misunderstood something but still wondering...
You need to pass a callback to the Meteor.call. The server can run it synchronously, blocking until it gets a return, but the client cannot so ticketSettingsObj will always be undefined.
See Meteor docs
Without error handling (and untested):
Meteor.call('getTicketSettings', function(error, result){
console.log(result);
_.map(result.tipos, function(tipo){
App.config.tickets.tipos.insert(tipo);
});
});
Do a console.log(App.config.tickets) and see if it returns a valid object. If it doesn't then you have defined the object App.config.tickets only on server side. If this is intentional and you only want this to be accessible on server side then then add a if(Meteor.isServer) or move the definition it to a file inside /server directory.

Error when calling http method from client in meteor

I am trying to consume a REST API in the meteor application. Inside the server.js file which is in the server folder, I have written this code:
Meteor.methods({
checkTwitter: function () {
this.unblock();
return Meteor.http.call("GET", "http://search.twitter.com/search.json?q=perkytweets");
}
});
Inside the client.js file, which is in the client folder, I have written down this code:
Meteor.call("checkTwitter", function(error, results) {
console.log(results.content); //results.data should be a JSON object
});
I get this error message in console:
"Exception while simulating the effect of invoking 'checkTwitter' Error: Can't make a blocking HTTP call from the client; callback required".
I have the callback function defined in client due to which I don't understand this error. What is it that I am doing wrong?
Meteor.http has been deprecated, please see the HTTP package.
I think that since there's a stub, "checkTwitter" will actually also run on the client. Once the server returns, its result will overwrite the result from teh client run.
In this case, since Meteor.http.call can't run on the client without a callback, you get the error.
Try changing:
Meteor.methods({
checkTwitter: function () {
this.unblock();
return Meteor.http.call("GET", "http://search.twitter.com/search.json?q=perkytweets");
}
});
With
Meteor.methods({
checkTwitter: function () {
if (Meteor.isServer) {
this.unblock();
return Meteor.http.call("GET", "http://search.twitter.com/search.json?q=perkytweets");
}
}
});

Meteor collection empty on client side

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).

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);
});

Resources