How to update the variable from the result of connection.query function? - javascript

I am creating a simple web application and am stuck on a simple problem. I want to update the temp variable from the results of my inner query. I know that connection.query might take some time, so the rest of the code is executed first. In the final response, I am not getting the value of temp.user_image and temp.user_name.
router.get("/home/getArticles", (req, res) => {
var select_query = "SELECT * FROM `articles` WHERE 1";
connection.query(select_query, async (err, result) => {
if (err) {
return res.status(500).json({ message: "Error while processing your request" });
}
var final_data = [];
for (var i = 0; i < result.length; i++) {
var temp = {};
let current_user_id = result[i].user_id;
var select_query = "SELECT * FROM `users` WHERE `user_id`=" + mysql.escape(current_user_id) + "";
connection.query(select_query, (err, innerResult) => {
if (err) throw err;
temp.user_name = innerResult[0].user_name;
temp.user_image = innerResult[0].user_profile_image;
});
temp.title = result[i].title;
temp.body = result[i].detail;
final_data.push(temp);
}
return res.status(200).json({ data: final_data });
})
})

There are 2 problems in your code:
The server response before the second query finish - which you've already known.
This way of querying relationship will result in extremely bad performance known as N+1 query problem
For an example, we can use SQL JOIN clause for querying relationship:
router.get("/home/getArticles", (req, res) => {
var select_query = "SELECT articles.*, users.user_name, users.user_profile_image AS user_image FROM `articles` LEFT JOIN `users` ON `articles`.`user_id` = `users`.`id` WHERE 1";
connection.query(select_query, async (err, result) => {
if (err) {
return res.status(500).json({ message: "Error while processing your request" });
}
return res.status(200).json({ data: result });
})
})

Related

Nodejs Return Stop for Loop

Here is the code, and when I run it, it only executes once...
export const postStock = (body) => {
for (let val of body.order.values()) {
let sql = ` INSERT INTO stockmaster (stocknum, cat_id, user_id, dyenumber, stockQty) VALUES ('${body.stocknum}', ${JSON.stringify(val.cat_id)}, '${body.user_id}', ${JSON.stringify(val.dyenumber)}, ${JSON.stringify(val.stockQty)})`;
return sql;
};
};
So, how do I run the for loop or prevent it from stopping?
Look at how the function works, and when the loop starts, it sends the response multiple times, so I tried to set it outside of the loop, but if I set it outside of the loop, how can I send an error in response?
So now I'm stuck here...!
static stock = async (req, res) => {
for (let i = 0; i < req.body.order.length; i++) {
const body = req.body;
connection.query(postStock(body, body.order[i]), (err, result) => {
if (err) {
res.status(500).json({
code: 0,
msg: "Fail",
emsg: "Server error: " + err.message
});
} else {
connection.query(updatepStock(body.order[i]), async (err, result) => {
if (err) {
res.status(500).json({
code: 0,
msg: "Fail",
emsg: "Server error: " + err.message
});
}
})
}
})
}
res.status(201).json({code: 1,msg: "success",emsg: "Stock arrived & Product Stock updated successfully"
})
}
return stops execution and exits the function. return always exits its function immediately, with no further execution if it's inside a for loop.
So you should avoid return in case you want the loop to continue. What you can do is store the sql into array or print the data without returning anything
You can use this. return makes the loop function to exit.
export const postStock = (body) => {
let values = body.order.values();
let sql = values.map((val) => `("${body.stocknum}",
"${JSON.stringify(val.cat_id)}", "${body.user_id}",
"${JSON.stringify(val.dyenumber)}", "${JSON.stringify(val.stockQty)}")`)
let query = "INSERT INTO stockmaster (stocknum, cat_id, user_id, dyenumber,
stockQty) VALUES " + sql
}

Wait for mysql to finish queries in a for loop before finishing a function in nodeJS

I am trying to run a query to get some data from a table, then use that array of data to get some data from another table to then return it as JSON.
I have been trying for a while but I cannot seem to figure out async and await. Right now it does sort of work but doesn't wait for my second query in the for loop to finish before returning data.
app.get("/get-top-trending", (request, response) => {
const req = request.query
let query = 'SELECT Ticker, Mentions FROM trend_data ORDER BY Date DESC, ' + req.by + ' DESC LIMIT 3';
let returnData = {};
cryptoDB.query(query, (err, tickers) => {
if (err) throw err;
getData(tickers).then(function() {
response.send(returnData)
});
});
async function getData(tickers) {
for (let i = 0; i < tickers.length; i++) {
cryptoDB.query('SELECT HistoricalJSON FROM historical_trend_data WHERE Ticker=? LIMIT 1', [tickers[i]['Ticker']], (err, rows2) => {
if (err) throw err;
returnData[tickers[i]['Ticker']] = rows2[0]['HistoricalJSON'];
});
}
}
});
I assume that something has to be done in the getData async function, however I am not particularly sure how to implement a working solution. I have tried promises but they don't seem to work the way that I expect.
Any guidance would be appreciated.
first solution:
app.get("/get-top-trending", (request, response) => {
const req = request.query
let query = 'SELECT Ticker, Mentions FROM trend_data ORDER BY Date DESC, ' + req.by + ' DESC LIMIT 3';
cryptoDB.query(query, (err, tickers) => {
if (err) throw err;
getData(tickers).then(function (returnData) {
response.send(returnData)
});
});
async function getData(tickers) {
const returnData = {};
const querys = ((ticker) => {
return new Promise((resolve, reject) => {
cryptoDB.query('SELECT HistoricalJSON FROM historical_trend_data WHERE Ticker=? LIMIT 1', [ticker['Ticker']], (err, rows2) => {
if (err) reject(err);
returnData[ticker['Ticker']] = rows2[0]['HistoricalJSON'];
resolve();
});
})
})
for (let i = 0; i < tickers.length; i++) {
await querys(tickers[i]);
}
return returnData
}
});
second solution:
app.get("/get-top-trending", (request, response) => {
const req = request.query
let query = 'SELECT Ticker, Mentions FROM trend_data ORDER BY Date DESC, ' + req.by + ' DESC LIMIT 3';
cryptoDB.query(query, (err, tickers) => {
if (err) throw err;
getData(tickers).then(function(returnData) {
response.send(returnData)
}).catch(error => throw error);
});
async function getData(tickers) {
let returnData = {};
for (let i = 0; i < tickers.length; i++) {
returnData[tickers[i]['Ticker']] = await getTickerQuery([tickers[i]['Ticker']]);
}
return returnData;
}
function getTickerQuery(ticker) {
return new Promise((resolve, reject) => {
cryptoDB.query('SELECT HistoricalJSON FROM historical_trend_data WHERE Ticker=? LIMIT 1', ticker, (err, rows2) => {
if (err) throw reject(err);
resolve(rows2[0]['HistoricalJSON']);
});
})
}
});
I recommend second solution for readability

Trouble setting a players ID and Username through callback

With an HTML5 game I am developing at the moment, I get the player's username and ID through a token sent in by the client which are all stored in a database. Everything was working perfectly up until I had to actually set the values for the player.
I've been searching all over the internet for similar problems that I am facing, and have come up with nothing. I am not sure if this is a variable scope problem or if I am taking the wrong approach to doing this.
Anyways, here's both the socket.player and getUserSession function
var newUserID;
var newUsersName;
socket.player = {
id: newUserID,
x: randomInt(100,400),
y: randomInt(100,400),
username: newUsersName
}
function getUserSession(sessionKey, callback){
var sql = "SELECT * FROM game_sessions WHERE unique_key=? AND still_active=?";
var stillActive = 1;
var returnData = [];
db.query(sql, [sessionKey, stillActive], function(err, result){
if (err){
throw err;
}
var numFound = result.length;
if (numFound == 1) {
//session was found
var userID = result[0].user_id;
returnData.push(result[0].user_id);
var sql2 = "SELECT * FROM users WHERE id=?";
db.query(sql2, [userID], function(err, result){
if (err){
throw err;
}
var uName = result[0].username;
returnData.push(result[0].username);
return callback(returnData);
});
}
});
}
And the callback function:
getUserSession(data.token, function(result){
newUserID = result[0];
newUsersName = result[1];
socket.broadcast.emit('newclient',socket.player);
});
I would do something like this:
function sqlQuery(sql, params) {
return new Promise((resolve, reject) => {
db.query(sql, params, function(err, result) {
if (err) {
return reject(err);
}
return resolve(result);
});
});
}
function getUserSession(sessionKey, callback){
const sql = "SELECT * FROM game_sessions WHERE unique_key=? AND still_active=?";
const stillActive = 1;
let returnData = [];
try {
return sqlQuery(sql, [sessionKey, stillActive])
.then(result => {
if (result.length === 1) {
//session was found
const userID = result[0].user_id;
returnData.push(result[0].user_id);
const sql2 = "SELECT * FROM users WHERE id=?";
return sqlQuery(sql2, [userID])
.then(result => {
const uName = result[0].username;
returnData.push(result[0].username);
return callback(returnData);
})
}
})
} catch (err) {
//handle err
}
}
Edit: if the callback function being passed in is an aync function, you'll probably need to modify the above snippet to await it.

Fetch data express js

Right now I am getting data from mysql in res.send but if I want to display two different records in different position (two different <ul>) then how can I do this?
Here is my code
connection.query('SELECT * FROM test',
function (err, rows, fields) {
if (err) throw err
var id =rows[0].number;
if (id != req.body.id) {
res.send("wrong accept");
} else {
var test = rows;
var length = Object.keys(rows).length;
const numberList = rows.map(row => row.number)
const numberLists = rows.map(row => row.test)
res.send({ number: numberList, text: numberLists })
}
})

Node Js callback return function

I want to return database value in node js and pass as a variable in ejs file.
Bellow is the code, Which I used. it did not return value.
function getExternalLocation(cb) {
mssql.connect(msSqlSettings, function (err ) {
if (err) {
cb(err);
}
var getQuery = "SELECT [Title] FROM [dbo].[StyleTemplates] " ;
//console.log(getQuery);
var request = new mssql.Request();
// query to the database and get the data
request.query(getQuery, function (err, rows) {
mssql.close();
cb(err, rows);
});
});
}
exports.eejsBlock_editbarMenuLeft = function (hook_name, args, cb) {
var userData = getExternalLocation(args, function(err, rows) {});
args.content = args.content + eejs.require(
'ep_resources/templates/editbarButtons.ejs', {
userData: userData
});
return cb();
})
userData did not return any value.
var userData = getExternalLocation(args, function(err, rows) {});
I don't think userData will get right data in async function, there is no await, so you can try to get data in callback.
getExternalLocation(args, function(err, rows) {
var userData = rows;
args.content = args.content + eejs.require(
'ep_resources/templates/editbarButtons.ejs', {
userData: userData
});
});

Categories