hi i'm newly learning nodejs and connected mysql database
now i want to save the result of a select query in a variable of some type but i cant.
var campGround = [];
console.log("Select Statement started....");
con.connect(function(error){
if(!error){
console.log("Connected");
var sql = "select * from campgrounds";
con.query(sql,function(err,result,field){
if (!err) {
// console.log(JSON.parse(result));
for(var i =0;i<result.length;i++)
{
try {
// console.log(result[i]);
setCampground(result[i]);
// campGround.push(result[i]);
} catch (error) {
console.log(error.message);
}
}
}
else{
console.log("Error while selecting record from campground table. ");
}
});
}else{
console.log("Error DataBase Not Connected!!! select statement");
}
});
function setCampground(value){
this.campGround.push(value);
}
console.log("length after execution :: "+campGround.length);
campGround.forEach(function(value){
console.log("Campground array");
console.log(value);
});
when i execute the above code and debug it...the select statement return from the database 3 records...but when i push them into the array ... and print the array nothing happens...please help
i cant find anything that could help me.
Your mysql query call is asynchronous (callback based) and your call to log the campGround is outside that callback so that means you are making a call but not waiting for that call to finish. That is the reason your campGround is not printing any thing.
You need to move following lines inside the callback where are are handling the error and response. something like this
const campGround = [];
console.log("Select Statement started....");
con.connect(function (error) {
if (!error) {
console.log("Connected");
const sql = "select * from campgrounds";
con.query(sql, function (err, result, field) {
if (!err) {
// console.log(JSON.parse(result));
for (let i = 0; i < result.length; i++) {
try {
// console.log(result[i]);
setCampground(result[i]);
// campGround.push(result[i]);
} catch (error) {
console.log(error.message);
}
}
} else {
console.log("Error while selecting record from campground table. ");
}
console.log(`length after execution :: ${campGround.length}`);
campGround.forEach(function (value) {
console.log("Campground array");
console.log(value);
});
});
} else {
console.log("Error DataBase Not Connected!!! select statement");
}
});
function setCampground(value) {
this.campGround.push(value);
}
You have:
const campGround = [];
that is global variable (or module scope);
Then in the code you have a function
function setCampground(value) {
this.campGround.push(value);
}
which is also in global scope (or module scope)
Therefore this.campGround is not campGround;
Change this.campGround .push(value); into campGround .push(value); and everything should work now.
Related
I am making a graph based web progrom. I am using nodejs.
I have a list of keys calls map which stores ID of vertices.
I want to retrieve the name of these vertices from MySQL using the ID. I have found a solution but I am not sure if it will work every time. This is my code.
for(var i=0;i<map.length;++i){
con.query('SELECT * FROM station WHERE id='+map[i],function(err,result,field){
if(err)
console.log("ERROR 3");
else{
result.forEach(function(r){
stationName.push(r.name);
})
if(stationName.length==map.length){
console.log(stationName);
res.render('route/showroute.ejs',{stationName: stationName});
}
}
})
}
I was wonder is it possible that my last map query loads before other query which may cause station name to be stored in wrong order. I am new to javascript.
You can do this using async await function
var getDataById = function (id) {
return new Promise(function (resolve, reject) {
con.query('SELECT * FROM station WHERE id=' + id, function (err, result, field) {
if (err) {
console.log("ERROR 3");
reject(err);
} else {
resolve(result);
}
});
});
};
(async function () {
for (var i = 0; i < map.length; ++i) {
var data = await getDataById(map[i]);
data.forEach(function (r) {
stationName.push(r.name);
});
if (stationName.length == map.length) {
console.log(stationName);
}
}
})();
You are worried about the query-function being asynchronous, and it is, but only with regard to what comes after the function. You're putting your stationNames into a new array inside the callback function which will be executed in sequence.
static listFunc() {
let funclist = [];
const queryList = "SELECT * FROM func";
mysqlModule.queryDB(database, queryList, (err, result) => {
console.log(result[0].id);
if (err) {
res.status(500).json({
"status_code": 500,
"status_message": "internal server error"
});
} else {
for (var i = 0; i < result.length; i++) {
let func = {
'id': result[i].id,
'psw': result[i].senha,
'nome': result[i].nome,
'DoB': result[i].dataNascimento,
'sexo': result[i].genero,
'morada': result[i].morada,
'permissoes': result[i].permissoes
}
funclist.push(func);
}
return funclist;
}
});
}
I created a function to give me all the workers from my DataBase and then store them inside funclist array.
The problem is the for loop is running before the query.
How can I run the loop only after query as finished?
Pass a callback function into listFunc:
static listFunc(callback){...}
Instead of returning the list just invoke the callback:
callback(funclist);
static listFunc() {
return new Promise((resolve,reject)=>{
let funclist = [];
mysqlModule.queryDB(database,"SELECT * FROM func", (err, result) => {
if (err) throw err;
result.forEach((result) => {
let func = {
'id': result.id,
'psw': result.senha,
'nome': result.nome,
'DoB': result.dataNascimento,
'sexo': result.genero,
'morada': result.morada,
'permissoes': result.permissoes
}
funclist.push(func);
});
resolve(funclist);
});
});
}
First i changed the "for" loop to a "each" loop and i used the promise to give me the data only after i get the query and the loop finished.
function clistFunc(req, res){
Func.listFunc().then((data)=>{
res.render('admin/adminListFunc', { funclist: data});
console.log(data);
}).catch(()=>{
console.log('Error');
});
}
Then i just rendered the jade only after my listFunc() return the pretended data.
I have three operations to do one after another
1.Fetch some rows from db
2.Another mysql query in forloop for getting some data and store in variable
3.Display the data
For that i am using async waterfall method.
async.waterfall([
function(callback){
//first sql and pass the result to second function
collection.getAllCollections(function (status,error,result) {
callback(null,result);
});
},
//running another query in loop with result with previous
function(result, callback){
for(var i=0;i<result.length;i++){
collection.getImages(result[i].id,function (status,error,user) {
//append the query result to old result
result[i]['users'] = user;
});
}
callback(null,result);
}
], function (err, result) {
console.log("result",result);
});
But the problem final result does not contains the user results because the second query(query in for loop is asynchronous)
You realised the problem at hand. Your callback basically has to wait for the for loop to end.
For example like this:
async.waterfall([
function(next){
//first sql and pass the result to second function
collection.getAllCollections(function (status,error,result) {
next(null, result);
});
},
function(result, next){
var calls = [];
//putting every call in an array
result.forEach(function(resultObject){
calls.push(function(callback) {
collection.getImages(resultObject.id, function (status, error, user) {
resultObject['users'] = user;
callback(null, resultObject);
});
}
)});
//performing calls async parallel to each other
async.parallel(calls, function(err, results) {
//executed as soon as all calls are finished
if (err) {
next(err, null);
} else {
next(null, results);
}
});
}
], function (err, result) {
console.log("result",result);
});
Documentation: http://caolan.github.io/async/docs.html#parallel
Some time ago I decided to switch from PHP to node. In my first projects I didn't want to use any ORM since I thought that I didn't need to complicate my life so much learning another thing (at the moment I was learning node and angular) therefor I decided to use mysql package without anything else. It is important to say that I have some complex queries and I didn't want to learn from sctratch how to make them work using one of the 9000 ORM node have, This is what I've been doing so far:
thing.service.js
Thing.list = function (done) {
db.query("SELECT * FROM thing...",function (err,data) {
if (err) {
done(err)
} else {
done(null,data);
}
});
};
module.exports = Thing;
thing.controler.js
Thing = require('thing.service.js');
Thing.list(function (err,data) {
if (err) {
res.status(500).send('Error D:');
} else {
res.json(data);
}
});
how can I promisify this kind of functions using bluebird ? I've already tried but .... here I am asking for help. This is what I tried
var Thing = Promise.promisifyAll(require('./models/thing.service.js'));
Thing.list().then(function(){})
I have done this way and it is working fine.
const connection = mysql.createConnection({.....});
global.db = Bluebird.promisifyAll(connection);
db.queryAsync("SELECT * FROM users").then(function(rows){
console.log(rows);});
I have never had much luck with promisifyAll and IMO I prefer to handle my internal checks manually. Here is an example of how I would approach this:
//ThingModule
var Promises = require('bluebird');
Things.list = function(params) {
return new Promises(function(resolve, reject) {
db.query('SELECT * FROM thing...', function(err, data) {
return (err ? reject(err) : resolve(data));
});
});
}
//usage
var thinger = require('ThingModule');
thinger.list().then(function(data) {
//do something with data
})
.error(function(err) {
console.error(err);
})
You can also create a function that fires SQL like this :-
function sqlGun(query, obj, callback) {
mySQLconnection.query(query, obj, function(err, rows, fields) {
if (err) {
console.log('Error ==>', err);
// throw err;
return (err, null);
}
console.log(query)
if (rows.length) {
return callback(null, rows);
} else {
return callback(null, [])
}
});
}
Where mySQLconnection is the connection object you get after mysql.createConnection({}).
After that, you can promisify the function and use the promise like below :-
var promisified = Promise.promisify(sqlGun);
promisified(query, {}).then( function() {} );
Completely new to nodejs, having trouble wrapping my head around asynchronous programming/callbacks. What I'm trying to do is:
On 'post', I want to gather all the words in a table in my database. I call it like so: var lesson_data = init_load_lesson(); This call to init_load_lesson() is from index.js in my 'routers' file made my express.
How do I construct a proper callback so that lesson_data is the results of my query?
var mysql = require('mysql');
var connection = require('./connection');
var data = [];
function init_load_lesson()
{
connection.connect();
var queryString = "SHOW COLUMNS FROM LessonOneVocabulary";
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
else
{
for (var i in rows)
{
data.push(rows[i].Fields);
console.log(data);
}
console.log(data);
}
});
connection.end();
}
module.exports = function() {
load_lesson();
};
To add a callback (try a few more functions and you'll get the hang of it):-
function init_load_lesson(callback) {
... // connect to database
if (err) {
callback(err);
} else {
// process item
callback(null, data);
}
}
init_load_lesson(function(err2, results) {
if (err2) {
// process error
} else {
// process results
}
});