Nodejs Printing Issue - node.js

This is my app.js file
var http = require('http');
var url = require('url');
var mysql = require('mysql');
var requestListener = function(request, response){
var urlParse = url.parse(request.url,true);
var path = urlParse.pathname;
var query = urlParse.query;
var jsonString;
if(path === "/getArticleById"){
var conn = mysql.createConnection({
host:'localhost',
port:'3306',
user:'root',
password:'root123',
database:'food'
});
conn.connect(function(err){
if(err){
console.log('Error connecting to database');
return;
}
response.writeHead(200, {'Content-Type': 'text/plain' });
});
var id = query.id;
conn.query('select * from article where id=?', id,function(err,rows){
if(err){
console.log(err);
}
jsonString = rows;
});
conn.end();
console.log(jsonString);
}
};
var server = http.createServer(requestListener);
server.listen(8080);
In jsonString which is inside conn.query, I am getting value of rows printed.
The last console.log is not printing anything, it is also jsonString.
Sorry, I am a newbie in node.js not aware of how to use objects.

Javascript is async in nature.
conn.query('select * from article where id=?', id,function(err,rows){
if(err){
console.log(err);
}
jsonString = rows;
});
Try printing the jsonString within the callback. So, your code should look like
conn.query('select * from article where id=?', id,function(err,rows){
if(err){
console.log(err);
}
jsonString = rows;
console.log(jsonString);
});
How your code is getting executed
Assignment to var id is getting done.
A query to db gets hit. This is time consuming process (async task), your callback function gets called when this query will get resolved. Note this will take some time, that means after sometime this callback will be called, where you will get the rows.
Just after calling the query() ( but before getting the result/callback), your next line of code, i.e conn.end() will get executed. Then you are trying to print the jsonString, Note, till now you haven't got the results back from DB (as it is async operation). That's why jsonString doesnot holds any value yet. Hence you didnt get result printed.
Solution:
print the jsonString after retrieving the result. that means, in the callback.

Related

Node.Js Retrieve specific data from SQL Server and encode it into JSON Array

I know this question have many duplicates, but I have already wasted too much time searching for the right solution.
First take a look at my Node.JS:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: 'myuser',
password: 'mypass',
server: 'myip',
database: 'mydatabase'
};
sql.close();
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
var dataqu = '';
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query("select * from AR_Invoices", function (err, recordset) {
if (err) console.log(err)
res.json(recordset);
sql.close();
});
});
});
var server = app.listen(5000,'0.0.0.0', function () {
console.log('Server is running..');
});
This code runs fine, but the json result structure is like this :
{"recordsets":[[{"Tipe":"Invoices","InvoiceID":411891,"InvoiceNumber":"SR.1701.0001"}]],"recordset":[{"Tipe":"Invoices","InvoiceID":411891,"InvoiceNumber":"SR.1701.0001"}],"output":{},"rowsAffected":[1]}
I don't know why but for some reason the result is always resulting in duplicate.
And how to just select InvoiceID and InvoiceNumber ?
I already tested using recordset.InvoiceID or recordset[0].InvoiceID but all is always in vain, and the result always in duplicate.
Can anyone explain how to do this properly?
I want the final result became like this :
[
{ "InvoiceID":"1", "InvoiceNumber":"mynumber" }
]
For the future reference, i finally got how to do this here is my full code
var express = require('express');
var app = express();
var dateFormat = require('dateformat');
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: 'myuser',
password: 'mypassword',
server: 'myip',
database: 'mydb'
};
sql.close();
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query("select top 2 'Invoices' as Tipe,InvoiceID,InvoiceNumber,InvoiceDate,(select top 1DriverPicture from dbDigitalApp.dbo.tbdriver) as Blob from AR_Invoices", function (err, result) {
if (err) console.log(err)
var myarr = new Array();
for (var i = 0; i < result.recordset.length; ++i) {
var InvoiceNumber = result.recordset[i].InvoiceNumber;
var InvoiceDate = dateFormat(result.recordset[i].InvoiceDate, "dd mmmm yyyy");
var Blob = result.recordset[i].Blob;
myarr.push({'InvoiceNumber':InvoiceNumber,'InvoiceDate':InvoiceDate,'Blob':Buffer.from(Blob).toString('base64')});
}
res.json(myarr);
sql.close();
});
});
});
var server = app.listen(5000,'0.0.0.0', function () {
console.log('Server is running..');
});
and the result of above code is like this :
answers
with above code you can get specific field only and do whatever you want with those specific data, such as change date format or encode base64.
i don't know if this the cleanest way to do this since the node.js has its own function using res.json that can set all field of retrieved data without need to loop through it.
But at least here is my kind of solution, hope it will be helpful to there future people who wondering the same thing like me.

page renders before getting all the values sorted

I think the rendering takes place before the searching of the string on the files, i have tried different methods but don't seems to get this working. any help will be appreciated. im a noob on to the nodejs. im trying to get the id of the user and query and get all the data and there after see if he is in any of the lists given and finally render the page.
const j = [];
let name = '';
const filename = [];
var ext = '';
module.exports = function(app, express) {
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/cusdetails', isLoggedIn, function (req, res) {
var cusid=req.body.cusid;
var insertQuerys = "SELECT * FROM customer WHERE cusid=? ORDER BY rowid DESC LIMIT 1";
connection.query(insertQuerys,[cusid],
function(err, rows){
rows.forEach( (row) => {
name=row.fncus;
});
fs.readdir('./views/iplist', function(err, files) {
if (err)
throw err;
for (var index in files) {
j.push(files[index])
}
j.forEach(function(value) {
var k = require('path').resolve(__dirname, '../views/iplist/',value);
fs.exists(k, function(fileok){
if(fileok) {
fs.readFile(k, function(err, content) {
if (err) throw err;
if (content.indexOf(name) > -1) {
ext = path.extname(k);
filename.push(path.basename(k, ext));
}
});
}
else {
console.log(" FileNotExist ");
}
});
});
});
console.log(filename);
res.render('cusdetails.ejs', {rows: rows, user:req.user , aml: filename });
});
})
You can create simple Promise wrapper and then use it inside async/await function to pause execution until resolved.
// use mysql2 package as it provides promise, less work to write promise wrappers
const mysql = require('mysql2/promise');
// create the connection to database
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'test'
});
// sample wrapper
function some(k) {
// more advisable to have local variables, why do you need this to be array?
var filename = [];
return new Promise((resolve, reject) => {
// doing this is also not recommended check nodejs documentation **fs.exists** for more info
fs.exists(k, function(fileok){
if(fileok) {
fs.readFile(k, function(err, content) {
if (err) reject(err);
if (content.indexOf(name) > -1) {
ext = path.extname(k);
filename.push(path.basename(k, ext));
resolve(filename)
}
});
}
else {
// reject(new Error("FileNotExist"))
console.log(" FileNotExist ");
}
});
})
}
// note the use of async
app.post('/cusdetails', isLoggedIn, async function (req, res) {
var cusid=req.body.cusid;
var insertQuerys = "SELECT * FROM customer WHERE cusid=? ORDER BY rowid DESC LIMIT 1";
// using await to pause excution, waits till query is finished
const [rows] = await connection.query(insertQuerys,[cusid])
rows.forEach( (row) => {
name=row.fncus;
});
// then you can
var result = await some(k)
...
Note however this way you loose the advantage of concurrent execution, as it's kindoff blocking. If the result of one call is not used in another, you can execute in parallel and await for result to achieve sequencing like
const [rows] = connection.query(insertQuerys,[cusid])
var result = some(k)
console.log(await rows) // do something
console.log(await result) // do something
JavaScript is asynchronous. This means that if you have a function with a callback (i.e. your query), the callback will be called asynchronously, at an unknown time, while the other code executes.
You need to look up some tutorials how to deal with callbacks, to get a proper understanding of it. Another method is using async/await and/or promises.
Basically, if you take the following code:
console.log("this will print first");
setTimeout(function () {
console.log("this will print last");
}, 1000);
console.log("this will print second");
If you run the code above, the top level is executed synchronously, so, it first calls console.log, then it executes setTimeout, which is synchronous. It sets a timeout, then says "I'm ready", and the code continues to the other console.log. After 1 second (1000 milliseconds), the callback in the setTimeout function is executed, and only then that console.log is called. You can not make the rest of the code wait this way, you need to restructure your code or read into promises.

RabbitMQ request, always timesout

I have a weird problem where my callback is never published and the message goes to timeout, even though the method runs in the queue. This happens in some specific queues and after it happens once, i cannot make any other requests from client which even previously worked, they all timeout. Have to restart the client and sever to make it working again.
This is the code, where its happening, and i cant seem to understand whats wrong.
Server.js file where i am creating the queues. I have several such queues, this is one of them.
var amqp = require('amqp');
var util = require('util');
var cnn = amqp.createConnection({host:'127.0.0.1'});
var getCart = require('./services/getCart');
cnn.on('ready', function() {
cnn.queue('getCart_queue', function(q){
q.subscribe(function(message, headers, deliveryInfo, m){
// util.log(util.format( deliveryInfo.routingKey, message));
// util.log("Message: "+JSON.stringify(message));
// util.log("DeliveryInfo: "+JSON.stringify(deliveryInfo));
getCart.handle_request(message, function(err,res){
cnn.publish(m.replyTo, res, {
contentType:'application/json',
contentEncoding:'utf-8',
correlationId:m.correlationId
});
});
});
});
});
Here, the handle request function is completed successfully, but the callback never goes through and its always timeout on the other end
var cart = require('../models/cart');
function handle_request(msg, callback) {
var user_id = msg.id;
cart
.find({id:user_id})
.populate('users ads')
.exec(function(err, results){
// This works, just the callback doesnt
if(!err){
console.log(results);
callback(null, results);
} else {
console.log(err);
callback(err, null);
}
});
}
exports.handle_request = handle_request;
this is how i am calling the request
var msg_payload = {"id":id};
mq_client.make_request('getCart_queue', msg_payload, function(err, results){
console.log(results); // never prints
//stuff that is never reached
});
These are my rpc files, i dont think there should be anything wrong with these, as some other queues work fine.
And this is the error shown on client
GET /getCart - - ms - -
Error: timeout 6ee0bd2a4b2ba1d8286e068b0f674d8f
at Timeout.<anonymous> (E:\Ebay_client\rpc\amqprpc.js:32:18)
at Timeout.ontimeout [as _onTimeout] (timers.js:341:34)
at tryOnTimeout (timers.js:232:11)
at Timer.listOnTimeout (timers.js:202:5)
Hope the information is not vague, if you need more, please let me know. Thanks!
I Think the error is in this file, because i tried debugging and from the rabbitmq server, the callback is being called and it has the correlation id as well as the reply to variable, so the request is not getting picked up here.
var amqp = require('amqp')
, crypto = require('crypto');
var TIMEOUT=8000;
var CONTENT_TYPE='application/json';
var CONTENT_ENCODING='utf-8';
var self;
exports = module.exports = AmqpRpc;
function AmqpRpc(connection){
self = this;
this.connection = connection;
this.requests = {};
this.response_queue = false;
}
AmqpRpc.prototype.makeRequest = function(queue_name, content, callback){
self = this;
var correlationId = crypto.randomBytes(16).toString('hex');
var tId = setTimeout(function(corr_id){
callback(new Error("timeout " + corr_id));
delete self.requests[corr_id];
}, TIMEOUT, correlationId);
var entry = {
callback:callback,
timeout: tId
};
self.requests[correlationId]=entry;
self.setupResponseQueue(function(){
self.connection.publish(queue_name, content, {
correlationId:correlationId,
contentType:CONTENT_TYPE,
contentEncoding:CONTENT_ENCODING,
replyTo:self.response_queue});
});
};
AmqpRpc.prototype.setupResponseQueue = function(next){
if(this.response_queue) return next();
self = this;
self.connection.queue('', {exclusive:true}, function(q){
self.response_queue = q.name;
q.subscribe(function(message, headers, deliveryInfo, m){
var correlationId = m.correlationId;
if(correlationId in self.requests){
var entry = self.requests[correlationId];
clearTimeout(entry.timeout);
delete self.requests[correlationId];
entry.callback(null, message);
}
});
return next();
});
};
This is the code for your make_request() in client.js file:
var amqp = require('amqp');
var connection = amqp.createConnection({host:'127.0.0.1'});
var rpc = new (require('./amqprpc'))(connection);
function make_request(queue_name, msg_payload, callback){
rpc.makeRequest(queue_name, msg_payload, function(err, response){
if(err)
console.error(err);
else{
console.log("response", response);
callback(null, response);
}
});
}
exports.make_request = make_request;
Look at what happens when you have an err on rpc.makeRequest():
rpc.makeRequest(queue_name, msg_payload, function(err, response){
if(err)
console.error(err);
//
//HERE: should be a callback call here.
//
else{
console.log("response", response);
callback(null, response);
}
});
This could be why you are getting a timeout. I hope it helps.
There wasn't a problem with rabbitMQ but with my queries in the handle request and after responding to the request.
For others coming with this problem, check and double check every statement, as the error will not show in the console, but will only show a timeout

module always returns null no matter what

I am new to node.js and was wondering why my code always return null.
I have db.js
exports.getItems = function(){
var conn = mysql.createConnection();
conn.connect();
conn.query("Select * From Items", function(err, rows, fields) {
if (err) throw err;
conn.end();
return rows;
});
};
and the module is called like this:
var db = require('../db.js');
exports.items = function(req, res){
var data = db.getItems();
console.log('second', data);
res.end(data);
};
and route:
app.get('/api/items', api.items);
The console.log('second') is always "second undefined". I have verified that the query is return items in the rows.
Please advice.
Classic async problem.
getItems is going to return before the database query is done. The data from the database is returned in the callback, not in the function itself.
When you write:
var data = db.getItems();
console.log('second', data);
res.end(data);
the value for data is undefined because you don't have a return statement inside getItems! So getItems returns undefined, as per the rules of JavaScript.
What you need is something like (and please understand I have not tested this) is:
exports.items = function(req, res){
var conn = mysql.createConnection();
conn.connect();
conn.query("Select * From Items", function(err, rows, fields) {
conn.end();
if (err) throw err;
res.end(rows);
});
}
See various sites online for managing connections cleanly. But this should be enough to get you to understand that the response should be sent from the callback of query which is where the data is actually available.

MongoDB is not producing output with Node.js

I am having trouble getting the output of a MongoDB query. When I call the save method:
db.users.save({email: "test#gmail.com", password: "test", sex: "male"},
function(err, saved) {
});
The code works, and stores the entry. However, the function (err, saved) isn't called, as far as I know. When I run this code:
var mongojs = require("mongojs");
var MONGOHQ_URL="mongodb://testUser:testPassword#paulo.mongohq.com:10085/app********";
app.get('/', function(request, response) {
var m = "hello";
var databaseUrl = MONGOHQ_URL;
var collections = ["users"];
var db = mongojs.connect(databaseUrl, collections);
var d = db.users.find({"sex":"male"}).limit(1);
response.send(d.email);
});
Then I get nothing. Is there something I'm missing?
var d = db.users.find({"sex":"male"}).limit(1) has no call back function so it goes out of scope and you dont see the response.
Two things first off i would use findOne instead of limit(1) and secondly you are missing the callback function, try this
db.users.findOne({"sex":"male"}, function (err, result) {
if(err){
console.log(err);
}else{
console.log(result);
//then do your response here
response.send(result.email);
}
});
Hope that makes sense.

Resources