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.
Related
I'm trying to make a MySQL query to filter data from a table. Effectively what I want to do is:
SELECT data FROM table WHERE column IN ?
The filter is coming from checkboxes in a form on a webpage, so I can pass an array or object fairly easily, but it'll be a varying number of parameters for the IN each time, so I can't us multiple ?. I tried making a for loop to make multiple queries concatenate the arrays that the queries returned, but I ran into scope issues with that. I also tried passing an array directly to the query, but that throws a syntax error. I'm sure there's a straightforward answer to this but I'm not sure how to do it.
Edit: source code added:
Here's where I'm at:
const filterShowQuery = `SELECT sl_Show.showId, sl_Band.BandName,
sl_Show.date, sl_Venue.venueName,
sl_Show.length, sl_Show.attendance, sl_Show.encore FROM sl_Show
JOIN sl_Band on sl_Show.BandID = sl_Band.BandId
JOIN sl_Venue on sl_Show.VenueId = sl_Venue.VenueId
WHERE sl_Band.BandName IN (?)
ORDER BY sl_Band.BandName;`;
Trying to get an array into the ? in WHERE sl_Band.BandName IN
const getShows = (req, res,next) =>{
var {bands, venues} = req.body;
var i = 0; //left over from previous attempt
var data = [];
for (b in bands){
mysql.pool.query(filterShowQuery, bands[b], (err, result) => {
if(err){
console.log('filter band error');
next(err);
return;
}
data = data.concat(result);
console.log(data); //data concatenates property and increases through for loop
})
// same action to be performed with venues once solved
// for (v in venues){
// conditions[i] = venues[v];
// i++;
console.log(data); //data is empty when logging from here or using in res
res.json({rows:data});
}
}
SECURITY WARNING!
I must to say: NEVER, NEVER PASS DATA DIRECTLY TO YOUR SQL!
If you don't know why, just google for SQL Injection. There are lots of examples on how it is done, how easily it can be done, and how to protect your application from this sort of attack.
You should always parametrize your queries. But in the very rare case which you really need to insert data concatenating a string into your sql, validate it before.
(E.g.) If it's a number, than use a Regex or some helper method to check if the value you are inserting into your SQL String is really and only a number and nothing else.
But aside that, you did not provide any source code, so it's really hard to give any help before you do that.
I need these values in a row, but I don't want them reply if its already in div.
My try is here. I try to build an array and put these values from firebase to here, but still I can't see in html.
var fruits = [];
var fetchPostsleft = function(postsRef, sectionElement,fruits) {
postsRef .orderByChild('timeStamp').on('child_added', function(data) {
console.log(data.val());
var author = data.val().senderName;
var containerElement2 = sectionElement.getElementsByClassName('posts-containerleft')[0];
fruits.push(data.val().senderName);
console.log(fruits.length);
});
};
fetchPostsleft(topUserPostsRef, topUserPostsSectionleft,fruits);
var fLen = fruits.length;
console.log(fruits.length);
for (var i = 0; i < fLen; i++) {
// text += "<li>" + fruits[i] + "</li>";
topUserPostsSectionleft.getElementsByClassName('posts-containerleft')[0].insertBefore( createheaders(fruits[i], ""),
topUserPostsSectionleft.getElementsByClassName('posts-containerleft')[0].firstChild);
}
The data is loaded from Firebase asynchronously. This means that by the time your looping over the array, it hasn't been populated yet. It's easiest to see this by replacing most of the code with a few log statements:
console.log("Before query");
postsRef.orderByChild('timeStamp').on('child_added', function(data) {
console.log("In child_added");
});
console.log("After query");
If you run this snippet, the logging will be:
Before query
After query
In child_added
This is probably not the order you expected, since it's different from the order the log statements are in your code. This is because the data is loaded from Firebase asynchronously and the rest of your code continues while it's loading.
It's slightly easier to see if you turn the callback into a separate function:
function onChildAdded(data) {
console.log("In child_added");
});
console.log("Before query");
postsRef.orderByChild('timeStamp').on('child_added', onChildAdded);
console.log("After query");
Now you can more easily see that the first few lines just declare the onChildAdded function. They don't run it yet. And we're just passing that function in to the query, so that the query can call onChildAdded whenever it gets the data.
This is the most common pitfall of web programming with remote servers. But since most of the modern web is based on such asynchronous APIs, you will have to learn it.
One way I've found that works is to reframe your problem. Your current code is based on "first fetch the posts, then add them to the HTML". But in asynchronous programming it's better to think "start fetching the posts. When we get them, add them to the HTML". This translates into the following code:
function fetchPostsleft(postsRef, sectionElement) {
postsRef.orderByChild('timeStamp').on('child_added', function(data) {
var author = data.val().senderName;
topUserPostsSectionleft.getElementsByClassName('posts-containerleft')[0].insertBefore(createheaders(author, ""),
});
};
fetchPostsleft(topUserPostsRef, topUserPostsSectionleft);
Now all the code that needs the new data is inside the callback, so it's only run when the snapshot is actually available.
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
}
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.
I'm messing around with node.js, using the Faker, underscore, mysql and randy libraries to add some test data to a web app.
So far so good-- but in one of my loops, the mysql call fails every time, but it also fails to generate any errors. I'm a bit stumped:
var sql = 'SELECT id FROM mytable WHERE 1';
client.query(sql, function(err, rows, fields){
// loop through results
_.each(rows, function (v, i){
// get the insert id
var id = v.id;
console.log (id); // prints valid ID
// generate other data
var stuff_count = randy.randInt(0,12);
_(stuff_count).times(function(n){
var sql = 'INSERT INTO other_table (linked_id, item_id) VALUES ('+id+','+randy.randInt(1,50)+')';
console.log(sql); // prints sql
client.query(sql, function(err, rows, fields) {
console.log(sql); // prints nothing
if (err){
console.log(sql); // prints nothing
throw err; // prints nothing
}
});
});
});
The looping logic is working fine and it gets all the way to where the sql should execute the INSERT against the other_table-- but tailing the mysql log shows nothing hitting the DB, and none of the debug statements inside the client.query block are printing anything, on success or failure.
assuming you are just running this standalone, your code probably finishes before it has a chance of doing the inserts.
place a setTimeout(..., 10000) after the _(stuff_count).times(...)
By using _().times(), you queue all the inserts, but are not waiting for completion. you should use a control flow library to ensure you wait for all inserts to complete.