NodeJS MySQL How to get the result outside of the query function - javascript

I can't seem to figure out how the get the result outside of a NodeJS MySQL Pool query. Here is some sample code to better explain what I mean.
var result = 'Hello world!';
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 100,
host : process.env.DB_HOST,
user : process.env.DB_USERNAME,
password : process.env.DB_PASSWORD,
database : process.env.DB_DATABASE
});
pool.query('SELECT * from user LIMIT 10', function (err, rows) {
result = rows;
});
res.send(result);
The above will return 'Hello world!' instead of the query.
If I console.log(result) inside the pool.query function it returns the rows from the query but I can't seem to get the data outside of the function. I've logged the function and checked all the associated functions and I think I'm just missing something basic.

You're sending the results back before the query finishes (and the callback is called). Sending the results in your callback will fix the problem:
pool.query('SELECT * from user LIMIT 10', function (err, rows) {
result = rows;
res.send(result);
});
As Aaron pointed out, this is a common problem. A more thorough answer can be found here.

The pool query function is asynchronous. It means that your code won't execute in the same sequence you declared the statements.
You start a query and you specify a callback function which should run when the query async operation completes.
The res.send will run immediately after the query and callback declaration and the callback will run much later. By the time you set the result you already send it.
Try to move your res.send inside the callback.
pool.query('SELECT * from user LIMIT 10', function (err, rows) {
res.send(rows);
});

Sorry if my English is bad,
I have facing the same problem with you and I found a solution where you can extract the result of your query function by mixing the async-await function with the promise
Look at my solution code here :
async () => {
const sqlQuery = `select * from contact;`
const promise = await new Promise((resolve, reject) => {
pool.query(sqlQuery, (err, result) => {
resolve(result)
})
})
console.log(promise)
})
With this code, your console definitely show the result of sqlQuery. How's this can be happen? The promise that you make will always has a pending status if the resolve/reject aren't being executed. With the mixing of asynchronus function and await in the promise that you make, your promise code has to be in resolve/reject status, if it's in pending status, they will not execute the next code, and always waiting until the resolve/reject has been executed. As you know, the result of your query statement shows in the callback function in pool.query. So why we don't execute the resolve/reject in the callback function of pool.query.
You can pass the result of query into the variable of your promise by adding it to the parameter of resolve function.

Related

node js postgres assign value to variable outside scope of then

I have to compare few rows derived from potgres with data derived from the dynamo DB. problem is in both cases i have to iterate over data & unless i can assign the value to a variable i will have to query the same data again from either one of two databases.
function postgressdata(sql){
return new Promise(function(resolve, reject) {
client_postgres.query(sql, (err, res) => {
resolve(res);
});
});
}
let get_creatives = postgressdata(sql);
get_creatives.then(function(result) {
console.log(result); // prints the result
let new_result = result;
}
console.log(new_result) // does not print result
How Can I assign the data to a variable here & use it anywhere?
I am a newbie to NODEJS so pardon me if I am asking silly question.
Nodejs is non-blocking.
so when this block of code runs
let get_creatives = postgressdata(sql);
get_creatives.then(function(result) {
console.log(result); // prints the result
let new_result = result;
}
console.log(new_result) // does not print result
what will happen is you will get nothing printed first because .then() will be called when the promise is resolved so this line
console.log(new_result) // does not print result
will be executed first which doesn't have the value yet obviously.
after that when the promise is resolved .then will be called and your value will be set.
now how to solve this?
I am assuming you're sending the value back to the callee so you can either use the async/await structure or you can use a callback, depending on how you need the value.
You can just keep a reference to the promise as your cache. A promise in JavaScript represents the result of an async operation, not the operation itself.
If you have something like:
async function runQuery() {
const result = await db.query(sql`SELECT * FROM creatives;`);
console.log('ran query');
return result;
}
const creativesPromise = runQuery();
async function useResult() {
console.log(await creativesPromise);
}
useResult();
useResult();
useResult();
even though we use the resulting list of creatives three times, "ran query" will only get logged once. Every use of the query results will need to be async, because you never know whether the query has finished running when you request the data, but the query will only be run once.

NodeJS - Sending SQL Results to Google Sheets

I am trying to write a script that will query a local database and send the results to a Google Spreadsheet. Where I am currently stuck and looking for help is how do I get the results of my query.
var myQuery = [];
function runQuery(query, callback) {
client.connect(function (err) {
if (err) throw err;
client.query(query, function (err, result) {
if (err) {
console.log(err);
}
callback({ result: result });
client.end(function (err) {
if (err) throw err;
});
});
});
}
runQuery('SELECT item_number FROM item WHERE item_number LIKE \'11-%\' LIMIT 10', function (resultsObject) {
myQuery = JSON.stringify(resultsObject.result.rows);
console.log('Did stringify work?');
console.log(myQuery);
});
console.log(myQuery);
My output:
Info: Start process (3:46:11 PM)
[]
Did stringify work?
[{"item_number":"11-0011"},{"item_number":"11-0012"},{"item_number":"11-1255"},{"item_number":"11-0052"},{"item_number":"11-0060"},{"item_number":"11-1256"},{"item_number":"11-1281"},{"item_number":"11-0659"},{"item_number":"11-0660"},{"item_number":"11-0054"}]
Info: End process (3:46:12 PM)
I think I understand what's happening, the scope of the variable myQuery is set and printed within the runQuery function just fine, but outside of that function it's not being actually set. How do I get around this?
Very new to JavaScript and NodeJS so I hope I'm using the correct terminology.
Thanks in advance!
The empty myQuery has already been consoled before you actually put values into it. This issue is caused by Javascript's Asynchronous mechanism. If you want to do something with the result, you have to use a callback function. Just like what you did when you accessed result from runQuery.
Another way to do it is promise. You can return a promise in some function and use the promise to access result.
If you decide to use promise, here is the code:
function getresult(parameters) {
return new Promise((resolve, reject) => {
runQuery(parameter, resolve, reject);
});
}
Using this function, you passed resolve as callback to runQuery. You do want to add another err callback function to catch err in runQuery. In promise you use reject as err callback.
When you want to do something with the result:
getresult(parameters)
.then((result) => {put your code here. result variable is your result})
.catch((err) => {do whatever with err});
This is not a scope issue. It is a timing issue. The query takes some time to execute. JavaScript is 'non-blocking' meaning it will start an asynchronous process (like doing a DB query - really virtually all I/O operations) and return the result later. In your code you are using a callback that is run once the data becomes available.
So, with that in mind, the way to think about your code is that you are doing things in this order:
1) declaring your function runQuery - this happens first since in JavaScript function declarations are moved to the top of the script they are in (a process called hoisting)
2) your variable myQuery is established and initialized (to an empty array)
3) your query is kicked off by a call to runQuery; this only starts the process
4) your console.log(myQuery) at the end of your script is run
5) some time later the query completes and your callback is called with the data where your other console.log() shows the returned data

promise pending error in mongodb and nodejs

I have written node.js code for getting some number using mongodb database.this is my code for that
MongoClient.connect('mongodb://localhost:27017/mongomart', function(err, db) {
assert.equal(null, err);
var numItems=db.collection('item').find({"category":category}).count();
callback(numItems);
});
This mongodb query runs correct on mongo shell but it is giving error when using with node.js
Promise <Pending>
I don't know what is this "promise" ? Please help..
node.js code is asynchronous so that numItems won't contain count of items - it rather contains Promise that contains count of items when resolved. You defenetely have to master the basics of node.js and asynchronous programming. Try to modify your code like this
MongoClient.connect('mongodb://localhost:27017/mongomart', function(err, db) {
assert.equal(null, err);
db.collection('item').find({"category":category}).count()
.then(function(numItems) {
console.log(numItems); // Use this to debug
callback(numItems);
})
});
For native Promise check out documentation https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise
Also look at bluebird promises https://github.com/petkaantonov/bluebird
A promise is a substitute temporary value that is given while you wait on the real value. To get the real value do
numItems.then(function (value) { callback(value) });
Or better yet, return the promise from your function, and let they implement it using the Promises pattern, instead of the callback pattern.
Had the same problem. Don't know if it's still relevant to you, but this is what solved it for me:
var category = 'categoryToSearch';
var cursor = db.collection('item').find({'category':category});
cursor.count(function (err, num) {
if(err) {
return console.log(err);
}
return num;
});
I drove myself bananas trying to solve a similar problem, where the document.save() option just gave Promise{pending} no matter what I did. Here's what I did:
Change (req,res) to async(req,res).
Change var post = doc.save() to var post = await doc.save().
Finally, log in to MongoDB web, and change accessible IP addresses to 0.0.0.0 (all addresses). Not doing this can cause issues sometimes even when your IP is whitelisted.
try this:
MongoClient.connect('mongodb://localhost:27017/mongomart', async (err, db) => {
assert.equal(null, err);
var numItems= await db.collection('item').find({"category":category}).count();
callback(numItems);
});
(adding the await and turn this function to async function)

Lines getting run in strange order

I'll try to keep this as simple as possible. The following function seems to run in a very strange manner. The output I'm getting from my test-prints is in the order of 1, 4, 3, 2 (with an empty returnList).
This seems to suggest that the code within the interior of these code-blocks are getting executed last, which as you might guess creates some problem when I want to return the returnList.
var server = new mongo.Server('localhost', 27017);
var db = new mongo.Db('tdp013', server);
app.get('/getall', function (req, res) {
var returnList = [];
console.log("1");
db.open(function(err, client){
client.collection("messages", function(err, col){
col.find({}, function(err, cursor){
cursor.each(function(err, item){
if(item!=null){
console.log("2");
returnList.push(item);
}
});
console.log("3");
});
});
});
console.log("4");
console.log(returnList);
res.sendStatus(200);
});
My question is simply this, is there a good explanation(in lack of a better word) as to why/how these lines are not getting executed in the written order?
Or alternatively, is there a way to return the returnList without doing it in the iteration?
This is simply the asynchronous nature that node.js further fortifies through the use of JavaScript.
You're trying to read this code and reason through its execution sequentially (i.e. synchronously), but that is not how it works.
console.log('1');
db.open(function (err, db) {
// ...
});
console.log('4');
Take the above snippet, for instance. You expect the function in db.open() to complete before it moves on to write 4 to the console, but that is not the case at all. What happens is that node will asynchronously run that open() method and continue on to the next code (here, that'd be console.log('4');). When that open() method has completed running, it'll kick off the callback function defined in the parameter list.
This is async JavaScript. You can't expect it to run the code in your editor synchronously/sequentially written like this.
Developing logic that will flow the way (it appears) you want it to flow, it would have to be refactored like the following:
var server = new mongo.Server('localhost', 27017);
var db = new mongo.Db('tdp013', server);
app.get('/getall', function (req, res) {
var returnList = [];
console.log("1");
db.open(function(err, client){
client.collection("messages", function(err, col){
col.find({}, function(err, cursor){
cursor.each(function(err, item){
if(item!=null){
console.log("3");
returnList.push(item);
}
else {
console.log("4");
console.log(returnList);
res.sendStatus(200);
}
});
console.log("2");
});
});
});
});
Node.js is asynchronous in nature and runs on single threaded event loop.
Example:
Let’s say you have triggered a database query and you are waiting for query to execute and then proceed further, but in a same time what will happen to the piece of code which are not dependent on that database query, they won’t execute and wait for their turn.
Asynchronous is exactly opposite of this. While you are doing database query Node.js will continue executing code and when database query will be done, it will come back to process it.
So in your case you have added console.log("2"); and console.log("3"); in callback function, so those lines are executing when those method executed. And console.log("4"); will not wait for db.open method to be finished. Hence the results are 1, 4, 3, 2.
So to make sure returnList returning correct data you have to add that in the callback method itself.
Hope this will help you to understand the problem you are facing.

Redis GET function returning undefined

I'm building a very simple client/server app using node.js and redis for the first time. After successfully firing up my redis client and my http server, I'm trying to do a simple SET/GET with my redis client.
I first do:
client.set('apple', 10, redis.print);
which returns a Reply:Ok.
Immediately after, I execute:
client.get('apple', function(err, reply) {
count = parseInt(reply);
return count;
});
Strangely, upon printing out count, I get undefined. But, if I use redis.print, such as:
client.get('apple', redis.print);
A Reply: 10 is returned in the console. 10 also shows up if I do a console.log(count).
I thought maybe I was misusing the set functions in the module, but after referring to these both, I am unsure of what's causing my errors:
node_redis - github readme
redis.io API - GET
upon printing out count, I get undefined.
client.get('apple', function(err, reply) {
count = parseInt(reply);
return count;
});
console.log(count); // is this where you get undefined?
// count at this point is, in fact, undefined,
// because it's set in a callback which was not yet fired.
I don't program in node.js, so I'm not sure about benefits of returning count from the callback. Where would it return it to? Isn't it supposed to be something like this?
client.get('apple', function(err, reply) {
count = parseInt(reply);
// do something with the count here. Print it or whatever.
});
Or you could trap it in a closure, but then you'll need to somehow wait for callback to return and set the variable. How it can be done - I have no idea.
var count = null;
client.get('apple', function(err, reply) {
count = parseInt(reply);
});
// TODO: wait for callback
console.log(count);
This is asynchonous, meaning the rest of the code is executed while waiting for the callback.
if you want to check if your set worked just print it :
client.get('apple', function(err, reply) {
console.log(reply);
});

Categories