Unable to access the variable in NodeJs function - javascript

I am using NodeJS postgresql client to fetch some data loop through it and give an output. I'm using ExpressJS together with postgresql client.
This is my code
var main_data = some array of data
var user_info = {}
for (var key in result.rows) {
var user = main_data[key].user
client.query('SELECT name,age,address FROM users WHERE user_id = $1 LIMIT 1;' , [user], function(queryErr, result){
var return_data = result.rows[0]
user_info.name = return_data.name
user_info.gender = return_data.gender
user_info.address = return_data.address
main_data[key].user_info = user_info
})
}
done()
res.json(main_data)
return
However when I run this code I don't get a proper output. The userinfo is not pushed to the main_data. It just outputs main_data variable just as the beginning of the code.
It is not simple as the suggested duplicate
Because the function sits inside a for loop so I can't just make the response call once the function is done. I have to wait till the whole loop is finished which may be 1000+ of loops to finish before I can make the response call.
So tell me how can I achieve it.
What am I doing wrong and how can fix it?
Thank you very much

I would use async.js for this, myself.
var rows = // your result.rows stuff.
function doTheQuery(item, callback){
// your query logic here, calling the callback with the results
}
async.series(rows, doTheQuery, function(err){
// handle any errors
}

Related

Node/JSON Issues

So I am trying to figure out why my returned object every single time is just []?
Here is my code:
var returnObject = [];
db.query(queryString, function(err, rows, fields) {
if (err) throw err;
for (var i in rows)
{
console.log('Data: ', rows[i]);
var marker =
{
o_ID:rows[i].o_ID,
data:rows[i].data
};
returnObject[i]=marker;
console.log(chalk.red(returnObject[i].o_ID));
console.log(chalk.red(returnObject[i].data));
}
});
var sqsParams = {MessageBody: JSON.stringify(returnObject), QueueUrl :'---'};
For some reasons when I print the returnObject values they are correct but when it gets to the JSON.stringify something happens and sends to my SQS queue just [].
I thought maybe getting rid of the marker variable and just assigning
returnObject[i]= {
o_ID:rows[i].o_ID,
data:rows[i].data
};
But that still results in the same issue. Any ideas? Thanks!
Database queries in JavaScript are usually asynchronous. This means that the code inside your callback function function(err, rows, fields) will be run only after the database query has been done, whereas you assignment to sqsParams will be done right after the database query has been started. The result is that code inside your callback function has not been run before you returnObject with JSON.stringify and it is still in its original value [].
Your sqsParams variable is being set outside the db.query callback. As the db.query is asynchronous, your code is going to just fall through with an empty array.
Move your sqsParams variable into the callback you are supplying to db.query, eg:
console.log(chalk.red(returnObject[i].o_ID));
console.log(chalk.red(returnObject[i].data));
}
var sqsParams = {MessageBody: JSON.stringify(returnObject), QueueUrl :'---'};
// Use sqsParams here
});

Parse Javascript SDK - Query causing 500 Internal Server Error

I have some Parse Cloud code that fetches and updates data in the Parse database.
app.get('/endpoint', function(request, response) {
var username = "name";
var something = "something";
var userFetchQuery = new Parse.Query(Parse.User);
userFetchQuery.equalTo("username", username);
userFetchQuery.first().then(function(foundUser) {
var fetchQuery = new Parse.Query("Call");
fetchQuery.equalTo("initiator", foundUser);
//fetchQuery.equalTo("status", 5);
return fetchQuery.first();
}).then(function(currentObject) {
var callObjectId = currentObject.id;
currentCall.set("something", something);
return currentCall.save();
}).then(function(success) {
response.send(ourResponse);
});
});
The code above works fine, however if I try to uncomment the line where I query the table by status (fetchQuery.equalTo("status", 5);), then I get the 500 internal error. Basically, I can't seem to query with both criteria (user and status).
Can't we have two equalTo() calls to the Parse.Query object? What could be wrong here?
======== EDIT 1 ========
If I query by both user and status, then I get no results back. If I query by just one of them, then I get data back. So, the question is: why are the two equalTo() statements causing the query to fail? I am 100% sure that I have appropriate data.
======== EDIT 2 ========
I have tried to isolate the issue by querying by any 2 fields of the table. Whenever there are two equalTo() statements, the query doesn't return anything. I have hardcoded the values for the equalTo() to make sure and result is always the same. Having more than one equalTo()s for Parse.Query() object results in 0 query results.

javascript callbacks for translation tool

I'm trying to build a translation engine using node.js. I have a Python/R background so I'm not getting the hang of these so called callbacks . . .
The input is a sentence :
var sentence = "I want to translate this"
When I hit the "Translate" button, it should trigger the translation.
Now this is the database query, I call a node.js backend at /translate
function query(string){
var query =
db.call.get(query, function(result){
if(result.length>0){
console.log(result[0].translation);
} else {
// not found in database
console.log(string);
}
});
}
So then it goes like this:
var wordList = sentence.split(" ");
for(i=0; i<wordList.length; i++){
// i call the database to return me the translation for each word
query(wordList[i]);
}
But then, the output in the console log comes like this:
output[0]: "translate", "want", "to", "I"
How can I make it come back in order? I understand there is some async and callback stuff going on, but I do believe that the guys who coded node are smart and that there is surely a way to solve this pretty easily.
Thanks
You need to take into account the fact that your query function might take a different time to return depending on the string argument you pass it. Right now, in your example code, if the query for "want" returns before the query for "I", then your translations will be outputted in the same order that the queries return (i.e. translation of "want", translation of "I").
Callbacks can help you get around this problem, because they are a function that will only get called when your query function returns. Then it's up to you to define what your program should do with the result. For instance, your program can output the results in the same order that the original array was in. This could be achieved using an index as suggested by Guffa, or using the async library that we will discuss later on.
So, one thing you could try is to pass query a callback like this:
function query(string, callback){
db.call.get(query, function(result){
if(result.length>0){
callback(null, result[0].translation);
} else {
// not found in database
callback(null, string);
}
});
}
The canonical way to use callbacks in Node.js, is to give it two parameters, so it looks like: callback(err, result). If there is no error, you can call callback(null, result), while when there is an error, you can call callback(err) or callback (err, result), depending on what you want to report.
Once your query function takes a callback, you are able to know when it did return a value, and you can use the async.map function (from the async library), like so:
var async = require('async');
var sentence = "I want to translate this";
var words = sentence.split(' ');
async.map(words, query, function (err, translations) {
console.log(translations);
}
What this function does, is:
run in parallel query on all the items in the words array
wait for all the callbacks from all the query functions to return
then call async.map's own callback (here the third argument:
function (err, translations) {console.log(translations);})
The only way to make them come back in order would be to chain the calls, but then you take away the point of having asynchronous calls in the first place.
Send along the index for the word also, that way you can put the results together in the right order:
var wordList = sentence.split(" ");
var resultList = [];
var resultCount = 0;
for (i = 0; i < wordList.length; i++){
// i call the database to return me the translation for each word
query(wordList[i], i);
}
function query(string, index){
var query = db.call.get(query, function(result){
if (result.length > 0){
resultList[index] = result[0].translation;
} else {
// not found in database
resultList[index] = string;
}
resultCount++;
if (resultCount == wordList.length) {
console.log(resultList);
}
});
}

Promise in node

I just started with node js and I'm in trouble in a procedure.
In my code, I get a list of items via json (array) and do a loop that list to see if there is a record in the database or not.
If there is no record in the database, I do an insert if there is I do an update.
The problem is that the system is going too fast over the query and does not wait for the result to see whether or not due to javascript asynchronously.
The need does he wait for the check query to return then continue and finally wait for the insert as well, for the insert must have the answer before continuing the loop "for".
The code would look like this:
var input = JSON.parse (req.param ('data'));
for (var i in input) {
iCode var = input [i] .codeOSNum;
qry = 'select count(*) as qtd from table where code = '+iCode; //need wait result from this query
var connection = new sql.Connection(config);
var request = new sql.Request(connection);
request.query(qry, function(err, recordset) {
if (recordset[0].qtd = 0) {
//do stuff to insert like: 'insert into blablabla' and need wait return.
} else {
//do stuff to update.
}
}); //and finally go to next item from loop 'for' and repeat until the end os json array.
}
I use indicated promise, but do not know how to use. I am newbie and desperate.

Angular JS Service Promise for Massaged Data

Hi I am new to Angular and javascript and need a bit of help.
I have a service that will need to aggregate data from various locations. I am building a sub-service to pull data from one of these locations. This subservice needs to 1) retrieve data from a REST web service, 2) massage it a bit and 3) return the final data to the invoking service.
I have steps 1 and 2 working, however I am running into a problem on the third. In general, I am having a hard time understanding promises. Yes, I've read the documentation, googled around, even saw a cartoon on it, still can't figure it out.... Anyway, here is the relevant code:
app.service('advsolr',['$http',function($http) {
var DEBUG = false;
var conf = get_conf();
var solr = 'serverurl';
var res = {};
var data = {};
this.query = function(searchp) {
//Run Search
query_solr(searchp);
return data;
};
var query_solr = function(search) {
var g = 'serverurl' //works fine
if (DEBUG) { console.log(g);}
$http.get(g).then(function(response){
res = response.data; // this works
parse_search_res(); //this massages the data and sticks it in the data object
return data; //this does absolutely nothing here
});
};
}]);
The main query method is ran by the other service. This queries a Solr instance, gets the results and massages them into the format I want. I know I can do this elsewhere, but I want to have this as a standalone service for portability and plus I just want this to work dammit.
So the query method runs, I had some other stuff in there, but I took it out for this example since it would not add value. It hits query_solr which gets the data and massages it with parse_search_res, which sticks it into the data global variable.
Now the issue is that query method returns the empty data before parse_search_res had a chance to load the data in it. How can I prevent the query method from returning without the data?
Thanks
The idea of promises is that you initiate some asynchronous operation like AJAX request, then you return corresponding promise object, and a consumer code uses this promise's methods to provide callback function on promise state change.
So to fix your code you need to make query_solr return promise:
app.service('advsolr', ['$http',function($http) {
var DEBUG = false;
var conf = get_conf();
var solr = 'serverurl';
var res = {};
var data = {};
var query_solr = function(search) {
var g = 'serverurl' //works fine
if (DEBUG) { console.log(g);}
return $http.get(g).then(function(response){
res = response.data; // this works
return parse_search_res();
});
};
this.query = function(searchp) {
return query_solr(searchp);
};
}]);
You'll also need to change parse_search_res() to return the massaged data instead of saving it into the "data" variable.
And having set up advsolr service like that, one could use it like this:
advsolr.query('something').then(function(data) {
console.log(data);
});

Categories

Resources