Still new to nodejs not sure what i am doing wrong here, i am trying to return a value from this function. However the variable i am trying to return outhjk is always reset.
function executeQuery( stmt, data ) {
var outhjk = "";
pool.connect(function(err, client, done) {
if(err) {
console.error('error fetching client from pool', err);
}
client.query(stmt, data, function(err, result) {
//call `done()` to release the client back to the pool
done();
if(err) {
return console.error('error running query', err);
}
outhjk = "just work please";
});
});
return outhjk;
}
your query is not operating inside pool.connect its directly returning var = "";
if you are using latest version of node.js you can use new Promise((resolve, reject)=>{});
or if older version use 'async' module or any other module to handle node.js asynchronous functions
client.query is asynchronous. The return statement : return outhjk; will be called before the function executes because return is faster...
The standard way to deal with this is to use a callback function :
function executeQuery( stmt, data, callback ) {
var outhjk = "";
pool.connect(function(err, client, done) {
if(err) {
console.error('error fetching client from pool', err);
}
client.query(stmt, data, function(err, result) {
//call `done()` to release the client back to the pool
done();
if(err) {
return console.error('error running query', err);
}
outhjk = "just work please";
callback(outhjk);
});
});
}
Then to call the function with a callback, you would do something like that :
var stmt = //stmt value here;
var data = //data value here;
executeQuery( stmt, data, function (outhjk) {
//here you can use outhjk
});
Read this to learn the gist off callbacks
Related
Here's my code
function getprefix(guildid) {
con.connect(function(err) {
con.query('SELECT * from ' + configcontent.guilds_table_name + ' WHERE guild_id=' + String(guildid), function(err, result) {
if (err) {
throw err;
} else {
return result[0].prefix;
}
});
});
}
I wanted to make this function to return one value from one column (from first result), but it returns undefined. When i tried to write it on screen (using console.log(result[0].prefix);) it works.
Please help. Sorry for bad description or english. Its my first question on StackOverflow
Your function is asynchronous, so it immediately returns result, now it returns undefined. Value from DB returned later, and passed to callback. You need to use promises(preferred)/callbacks to return async results from your function, something like this:
function getprefix(guildid) {
return new Promise((resolve, reject) => {
con.connect(function (err) {
con.query('SELECT * from ' + configcontent.guilds_table_name + ' WHERE guild_id=' + String(guildid), function (err, result) {
if (err) {
// throw err;
// instead of throwing we passing error to result promise
reject(err)
} else {
// return result[0].prefix;
// instead of return we pass result to promise
resolve(result[0].prefix)
}
});
});
}
}
so usage will look like:
getprefix(guildid)
.then(prefix => console.log(prefix))
.catch(e => console.err('Unable to get prefix', e))
it would be great to check the different ways to handle async programming in JS with callbacks/promises/async awaits in details.
You can't return value from a callback.
Before you make your query, connect to the db. Don't use the callback function for that, cuz making a query supposed to be made with con.query
function getprefix(guildid) {
con.connect();
con.query('SELECT * from ' + configcontent.guilds_table_name + ' WHERE guild_id=' + String(guildid), function(err, result) {
if (err) {
throw err;
} else {
// do stuff with 'results'
}
});
EDIT
You can use async/await like this to get access to the return value, but you have to wrap your code in an IIFE (Immediately Invoked Function Expression) or use top level await, but it's only available in the latest version of Node.
Note, that I only used IIFE, because I don't have any other function or logic where I could call my query. If you call it in another function, make it async.
// Top level action
(async () => {
const output = await makeQuery();
console.log(output);
})();
// Query
function makeQuery() {
return new Promise((resolve, reject) =>
db.query("SELECT * FROM users", (err, res) => {
if (err) reject(err);
else resolve(res);
})
);
}
i'm trying create first node js api.
i wroted this code but when i start server.js it's not working.
here code :
var executeQuery = function(res, query){
sql.connect(dbConfig, function (err) {
if (err) {
console.log("Error while connecting database :- " + err);
res.send(err);
}
else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function (err, res) {
if (err) {
console.log("Error while querying database :- " + err);
res.send(err);
}
else {
res.send(res);
}
});
}
});
}
when i start it error say :
C:\node\atlasErpApi\server.js:47 res.send(res);
TypeError: res.send is not a function at C:\node\atlasErpApi\server.js:47:43
You are declaring a new variable res as argument to your request.query callback which shadows the res the comes as argument to your executeQuery function.
This should be most obvious at the line res.send(res) which, if you think about it, doesn't make sense at all.
Use different variable names for the two. For example, change the inner one to sqlRes:
var executeQuery = function(res, query) {
sql.connect(dbConfig, function(err) {
if (err) {
console.log("Error while connecting database :- " + err);
res.send(err);
} else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function(err, sqlRes) { // <<< CHANGED to sqlRes
if (err) {
console.log("Error while querying database :- " + err);
res.send(err);
} else {
res.send(sqlRes); // This makes more sense now :-)
}
});
}
});
}
Note: Technically this also happens for err - you have an err from request.query's callback shadowing the err from sql.connect's callback. But this usually doesn't matter because you won't need to use the outer err in the inner callback.
I have the following code:
updateDocument = (data) => {
Cloudant(CONN_STRING, (err, cloudant) => {
if (err) {
throw new Error('Failed to initialize Cloudant: ' + err.message);
}
let db = cloudant.db.use('my-db')
db.insert(data, (err, result) => {
if (err) {
throw new Error('Failed to initialize Cloudant: ' + err.message);
}
else {
console.log(result);
}
})
});
}
I would like for updateDocument() to return the result db.insert provides. However, if I try to return a variable it is undefined (I believe because of the async calls). I've tried async and await, but I may not have set them up properly because they also didn't work.
Thanks for any help!
This is a "JavaScript is asynchronous" problem. You could simplify your updateDocument function like so:
updateDocument = (data) => {
var cloudant = Cloudant({ url: CONN_STRING, plugin: 'promises');
let db = cloudant.db.use('my-db')
return db.insert(data);
}
This is using the Cloudant library with the "promises" plugin. JavaScript Promises help you manage asynchronous calls without passing callback functions around.
You would call this code like so:
updateDocument({a: 1, :b})
.then((data) => {
console.log('success!', data);
}.catch((e) => {
console.log('oops!', e);
});
Success arrives at 'then', failure arrives in the 'catch' clause.
I have written below code in one file:
models/exported.js
module.exports = {
processedList: function(store_name) {
var t;
var tradeIds = exported.find({storename: store_name}, function (err, value) {
if (err) return console.error(err);
return value;
}).select('tid -_id');
}, // Export connection here
};
I have another file in routes
routes/exported.js
var exported = require('../models/exported.js');
var tradeIds = exported.processedList(storename);
console.log('simer'+tradeIds);
}
but I get undefined in console.log. If instead of return statement in processedlist I write console.log then the result gets console. But my requirement is to return data from model file to route file.
I am new to express and node js.
I guidance would be highly appreciated.
Acoording to your question, you want calling a function from route and get return response from your function to route. simple use callback functions.
models/exported.js
module.exports = {
processedList: function (store_name, callback) {
var t;
var tradeIds = exported.find({storename: store_name}, function (err, value) {
if (err) {
callback("error", err)
} else {
callback("success", value)
}
}).select('tid -_id');
}
}
routes/exported.js
var exported = require('../models/exported.js');
exported.processedList('storename', function (err, results) {
if (err == 'error') {
console.log(err);
} else {
console.log(results);
}
});
You are trying sync operation in async environment. processedList may or may not have completed when you try to console log tradeIds. NodeJS would not wait for it to complete because it is asynchronous in nature (by design and it is not a bug). You can pass callback rather than executing this way.
models/exported.js
module.exports = {
processedList: function(store_name, cb) {
var t;
var tradeIds = exported.find({storename: store_name}, function (err, value) {
if (err) return cb(err);
cb(null, value);
}).select('tid -_id');
}, // Export connection here
};
routes/exported.js
var exported = require('../models/exported.js');
exported.processedList(storename, function(err, results) {
if (err) { console.log(err); }
console.log(results);
});
This makes sure that console.log happens only when processedList finishes execution.
I'm struggling with passing data concept in Node.js.
Let's take SQL tedious as example. Here is code from examples:
//acquire a connection
pool.acquire(function poolAcquire(err, connection) {
if (err) { console.error(err); return; }
//use the connection as normal
var request = new Request('select 1;select 2;select 3', function requestCallback (err, rowCount) {
if (err) { console.error(err); return;}
console.log('rowCount: ' + rowCount);
//release the connection back to the pool when finished
connection.release();
});
request.on('row', function onRequestRow(columns) {
console.log('value: ' + columns[0].value);
});
connection.execSql(request);
});
pool.acguire takes function as the argument and this function has particular signature (err,connection)
My question is - how do I pass SQL statement inside this function?
I cannot change signature because different function signature is not called.
Also I cannot use global scope because variable may be changed outside.
In other words I need to find way to bypass wrappers calls and still pass some data.
Something like
var mySQLs = ['select 1;select 2;select 3','select 4;select 5;'];
async.forEach(mySQLs,WorkWithOneItem, AllIsDone);
function WorkWithOneItem(item, callback){
pool.acquire(?????(item));
callback(); // tell async that the iterator has completed
}
function AllIsDone (err) {
console.log('All done');
}
By wrapping it in another function:
function aquire(sql, callback) {
pool.acquire(function poolAcquire(err, connection) {
if (err) { console.error(err); return callback(); }
//use the connection as normal
var request = new Request(sql, function requestCallback (err, rowCount) {
if (err) { console.error(err); return;}
console.log('rowCount: ' + rowCount);
//release the connection back to the pool when finished
connection.release();
callback();
});
request.on('row', function onRequestRow(columns) {
console.log('value: ' + columns[0].value);
});
connection.execSql(request);
});
}
function WorkWithOneItem(item, callback){
acquire(item, () => {
callback(); // tell async that the iterator has completed
});
}
Do you need the results out as well?
var mySQLs = ['select 1;select 2;select 3','select 4;select 5;'];
async.forEach(mySQLs, WorkWithOneItem, AllIsDone);
function WorkWithOneItem(sql, callback){
pool.acquire(function poolAcquire(err, connection) {
if (err) return callback(err);
//use the connection as normal
var request = new Request(sql, function requestCallback (err, rowCount) {
if (err) return callback(err);
console.log('rowCount: ' + rowCount);
//release the connection back to the pool when finished
connection.release();
});
var rows = [];
var count = 0;
request.on('row', function onRequestRow(columns) {
console.log('value: ' + columns[0].value);
rows.push(columns[0].value); // or whatever you actually want out of these.
});
request.on('done', function onRequestDone() {
callback(null, rows);
});
connection.execSql(request);
});
callback(); // tell async that the iterator has completed
}
function AllIsDone (err) {
console.log('All done');
// you probably want async.map, so you can get the result back
// as the second argument for a function like this
}