Meteor.method hangs on call - javascript

I have a meteor code that calls an method on the server. The server code executes an API call to the USDA and puts the resulting json set into a array list. The problem is that after the Meteor.call on the client side, it hangs.
var ndbItems = [];
if (Meteor.isClient) {
Template.body.events({
"submit .searchNDB" : function(event) {
ndbItems = [];
var ndbsearch = event.target.text.value;
Meteor.call('getNDB', ndbsearch);
console.log("This doesn't show in console.");
return false;
}
});
}
if (Meteor.isServer) {
Meteor.methods({
'getNDB' : function(searchNDB) {
this.unblock();
var ndbresult = HTTP.call("GET", "http://api.nal.usda.gov/ndb/search/",
{params: {api_key: "KEY", format: "json", q: searchNDB}});
var ndbJSON = JSON.parse(ndbresult.content);
var ndbItem = ndbJSON.list.item;
for (var i in ndbItem) {
var tempObj = {};
tempObj['ndbno'] = ndbItem[i].ndbno;
tempObj['name'] = ndbItem[i].name;
tempObj['group'] = ndbItem[i].group;
ndbItems.push(tempObj);
}
console.log(ndbItems); //This shows in console.
console.log("This also shows in console.");
}
});
}
After the call to the server and the API returns data to the console and writes it to the array, it doesn't process the console.log on the client side 1 line below the method call. How can I fix this?

You forgot to give your client side call a callback function. Method calls on the client are async, because there are no fibers on the client. Use this:
if (Meteor.isClient) {
Template.body.events({
"submit .searchNDB" : function(event) {
ndbItems = [];
var ndbsearch = event.target.text.value;
Meteor.call('getNDB', ndbsearch, function(err, result) {
console.log("This will show in console once the call comes back.");
});
return false;
}
});
}
EDIT:
You must also call return on the server:
if (Meteor.isServer) {
Meteor.methods({
'getNDB' : function(searchNDB) {
this.unblock();
var ndbresult = HTTP.call("GET", "http://api.nal.usda.gov/ndb/search/",
{params: {api_key: "KEY", format: "json", q: searchNDB}});
....
console.log("This also shows in console.");
return;
}
});
}

Related

Backbone - Can't get attributes

I have a function which does a fetch, it returns successful and sets the data.
But I can't work out how to get the data out of the model again.
fetchAcceptedTerms: function () {
var self = this;
this.appAcceptedTerms = new T1AppAcceptedTerms();
this.acceptedTerms = new AppAcceptedTerms();
this.acceptedTerms.fetch({
success: function (data) {
console.log(data);
if (data.meta.status === 'success') {
self.appAcceptedTerms.set(data.data);
}
}
});
console.log(self.appAcceptedTerms);
console.log(self.appAcceptedTerms.attributes);
},
See output in console:
http://s32.postimg.org/ssi3w7wed/Screen_Shot_2016_05_20_at_14_17_21.png
As you can see:
console.log(data); returns the data as expected
console.log(self.appAcceptedTerms); the data is set correctly as we can see it in the log
console.log(self.appAcceptedTerms.attributes); isn't working properly and returns Object {}
Can someone help on how to get all of the attributes out?
Thanks
The fetch operation is asynchronous, so you need to check for your attributes after the fetch operation has completed. Does the below output your attributes as expected?
fetchAcceptedTerms: function () {
var self = this;
this.appAcceptedTerms = new T1AppAcceptedTerms();
this.acceptedTerms = new AppAcceptedTerms();
this.acceptedTerms.fetch({
success: function (data) {
console.log(data);
if (data.meta.status === 'success') {
self.appAcceptedTerms.set(data.data);
console.log(self.appAcceptedTerms);
console.log(self.appAcceptedTerms.attributes);
}
}
});
}

Parse [Error]: success/error was not called (Code: 141, Version: 1.9.0)

I am trying to write a Cloud Code function that will allow me to edit the data of another user as I cannot do that in the application it self. What the code does (I should say tries to do as I don't know JS) is fetch a User object and a Group (a class I created) object using two separate queries based on the two object IDs inputed. Here is my code
Parse.Cloud.define("addInvite", function(request, response) {
Parse.Cloud.useMasterKey();
var userID = request.params.user;
var groupID = request.params.group;
var user;
var group;
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo("objectId", userID);
return userQuery.first
({
success: function(userRetrieved)
{
user = userRetrieved;
},
error: function(error)
{
response.error(error.message);
}
});
var groupObject = Parse.Object.extend("Group");
var groupQuery = new Parse.Query(groupObject);
groupQuery.equalTo("objectId", groupID);
return groupQuery.first
({
success: function(groupRetrieved)
{
group = groupRetrieved;
},
error: function(error)
{
response.error(error.message);
}
});
var relations = user.relation("invited");
relations.add(group);
user.save();
response.success();
});
Every time I execute the method I get the error:
[Error]: success/error was not called (Code: 141, Version: 1.9.0)
Can anyone help with this? Thanks.
Every function in Parse Cloud returns a Promise. This also includes any query functions which you run to retrieve some data. Clearly in your code you are returning a Promise when you execute a query which abruptly ends your cloud function when your query completes. As you do not call a response.success() or response.error() in any of the success blocks, your cloud function returns without setting a suitable response, something that Parse requires and hence the error. Your code needs to chain all the promises to ensure your code is executed correctly and return success/error in the last step:
Parse.Cloud.define("addInvite", function(request, response) {
Parse.Cloud.useMasterKey();
var userID = request.params.user;
var groupID = request.params.group;
var user;
var group;
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo("objectId", userID);
userQuery.first().then(function(userRetrieved) {
user = userRetrieved;
var groupObject = Parse.Object.extend("Group");
var groupQuery = new Parse.Query(groupObject);
groupQuery.equalTo("objectId", groupID);
return groupQuery.first();
}).then( function(groupRetrieved) {
//group = groupRetrieved;
var relations = user.relation("invited");
relations.add(groupRetrieved);
return user.save();
}).then(function() {
response.success();
}, function(error) {
response.error(error.message);
});
});

Meteor HTTP.call undefined on Client-side, working on Server-side

I am currently trying to learn how to do HTTP requests in Meteor. When I run the code, I can properly see the data in the console. However, on the client side all I get is "undefined". I believe I'm running the HTTP.get method synchronously.
.JS file
if (Meteor.isClient) {
Template.test.helpers({
testGET: function(){
var origin = Meteor.call('fetchFromService');
console.log(origin); //-- Displays 'Undefined'
}
});
}
if (Meteor.isServer) {
Meteor.methods({
fetchFromService: function() {
this.unblock();
var url = "https://httpbin.org/get";
var result;
try{
result = HTTP.get( url );
} catch(e) {
result = "false";
}
console.log(result.data.origin); //-- Displays the data properly
return result.data.origin;
}
});
}
It's async, you have to pass a callback to the call function:
var origin = Meteor.call('fetchFromService', function(err, data) {
console.log(data);
});
If you don't pass the callback, origin will be undefined until the request finishes.

JavaScript not getting function returns in Node.js

I have made an IRC bot for purely learning purposes but I have a Minecraft server that I use an API to get the status back as JSON. Now I have made the code and it works but for some reason when I try and use a return on the function so I can get the content it seems to not work?
So I have the two functions below:
function getservers(name) {
if (name == "proxy") {
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
return data.motd;
});
} else if (name == "creative") {
var Request = unirest.get(creative);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
return data;
});
} else if (name == "survival") {
var Request = unirest.get(survival);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
return data;
});
}
}
// Main logic:
function parsemessage(msg, to) {
// Execute files
function pu(o,t,f){if(o)throw o;if(f)throw f;bot.say(to,t)}
if (msg.substring(0,1) == pre) {
// Get array
msgs = msg.split(' ');
console.log(msgs[0]);
// Run Login
if (msgs[0] == pre+"help") {
bot.say(to, "Help & Commands can be found here: https://server.dannysmc.com/bots.html");
} else if (msgs[0] == pre+"status") {
// Get status of server, should return online/offline - player count for each server - motd
server = getservers("proxy");
console.log(server);
/*var data = '';
var Request = unirest.get('https://mcapi.us/server/status?ip=185.38.149.35&port=25578');
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
});
} else if (msgs[0] == pre+"players") {
// Should return the player list for each server
} else if (msgs[0] == pre+"motd") {
// Should return the message of the day.
} else if (msgs[0] == pre+"ip") {
bot.say(to, "ShinexusUK IP Address: shinexusuk.nitrous.it");
} else if (msgs[0] == pre+"rules") {
}
}
}
The code in the getservers() function works, when I do the
console.log(data["motd"]);
It outputs my servers message of the day. But when I do return
data.motd
(same as data["motd"]?) The code that calls the function is here
server = getservers("proxy");
console.log(server);
Please note this is a node.js code and it contains many files so i can't exactly paste it. So here is the link to the github repo with the whole node application: Here
When the function getservers is called, it makes an asynchronous request and return nothing.
Then the callback is fired with the response of that request as parameter.
Note that the function getservers will end before the end callback of your request is called
(simplified version)
function getservers(name) {
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
return data.motd;
});
// nothing returned here
}
What you need is a function callback that will be called after you got the response.
function getservers(name, callback) { // callback added
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
callback(data.motd); // fire the callback with the data as parameter
});
// nothing returned here
}
And then you can use your function like this :
getservers("proxy", function(server){
console.log(server);
....
})

Titanium Studio hold function execution until another function completes

Hey all I'm trying to get a window populated with a table view that is populated from a network function in Titanium Studio, build: 2.1.1.201207271312. I have the data being fetched properlybut the problem is that the program continues to run without waiting for the table view to be populated properly. Here's the code:
ui.js:
bs.ui.createTransitRoutesListWindow = function() {
var winbsRoutesList = Titanium.UI.createWindow({
});
var tv2 = Ti.UI.createTableView();
tv2 = bs.ui.createbsRouteListTableView();
winbsRoutesList.add(tv2);
};
bs.ui.createbsRouteListTableView = function() {
var tv = Ti.UI.createTableView();
Ti.API.info('populating data');
var busStopList = bs.db.routeStopList();
tv.setData(busStopList);
return tv;
};
db.js:
bs.db.routeStopList = function() {
var stoplist = [];
bs.net.getRoutes(function(data) {
Ti.API.info('data length: '+data.length);
for (var i = 0;i<data.length;i++) {
stoplist.push({
title:data[i].stopName,
id: i
});
}
});
return stoplist;
}
network.js
bs.net.getRoutes = function(_cb) {
var xhr = Titanium.Network.createHTTPClient();
xhr.onload = function() {
_cb(JSON.parse(this.responseText));
Ti.API.info(this.responseText)
};
xhr.onerror = function(event) {
}
xhr.open("GET","<URL to valid JSON>", true);
//+ Ti.App.Properties.getString('currentBus','This is a string default')
xhr.send();
};
bussearch.net.getRoutes() is an AJAX operation and thus it is asynchronous. This means that the code will NOT wait for it to complete. The code will proceed while the response is going. The time it will respond is not known also.
If you want to do something after the data returns, you should do everything in the callback instead or create deferred objects like jQuery (which are basically callback containers).
//db.js
bussearch.db.routeStopList = function(callback) {
var stoplist = [];
bussearch.net.getRoutes(function(data) {
....
callback.call(this,stoplist);
});
}
//ui.js
bussearch.ui.createBussearchRouteListTableView = function(callback) {
var tv = Ti.UI.createTableView();
Ti.API.info('populating data');
bussearch.db.routeStopList(function(busStopList){
tv.setData(busStopList);
callback.call(this,tv);
});
};
//calling createBussearchRouteListTableView()
createBussearchRouteListTableView(function(tv){
//tv in here is the data
//do inside here what you want to do to tv after it's retrieved
});

Categories