Nodejs + redis + displaying results on the browser - node.js

I am having trouble displaying the results that I retrieve from redis with the redis driver in nodejs.
I display an array that initially was a JSON, but it displays lots of "/n" between the elements and properties and I have spent hours trying to fix it but I did not succeed.
Any hint about how can I present the information in the browser without the "/n" characters?
JSON.stringify? I have try it and no way. util.inspect... I have try it. I know I am doing something wrong but I cannot find what.
My code goes like this:
app.get('/retrieve_from_redis_promise', function(req, res) {
client.on('connect', function() {
console.log('Connected to Redis succesfully');
});
var p = new Promise(function(res, reject) {
if (true) {
client.hgetall("redis_db_name", function(err, replies) {
res(replies)
// Object.keys(replies).forEach(key => {});
});
} else {
reject(Error("It broke"));
}
});
p.then(function(result) {
res.send(result); // "Stuff worked!"
}, function(err) {
console.log(err); // Error: "It broke"
});
});

Try
client.hgetall("redis_db_name", function(err, replies) {
Object.keys(replies).forEach(key => {
replies[key] = JSON.parese(replies[key]);
});
res(replies)
});

Related

Cannot set headers after they are sent to clients in node.js

My code is not working . I am beginner and don't know my problem. Kindly help.I have seen one or two solution on stackoverflow but didnot get .
This is code.
app.post('/post',(request,response)=>{
var description=request.body.description;
var contact_number=request.body.contact_number;
var city=request.body.city;
var budget=request.body.budget;
var category=request.body.optradio;
var query=connection.query("insert into jobs(Jobs_id,Description,Category,City,Contact_number,Budget) values(?,?,?,?,?,?)",[null,description,category,city,contact_number,budget],function(err){
if(err)
console.log(err);
else
response.send("successful");
});
response.redirect('/data');
});
app.get('/data',function(request,response){
connection.query("SELECT * FROM jobs ORDER BY Jobs_id DESC",(err, rows,fields) => {
if(err) {
console.log(err);
}
else {
response.render('feed', {title : 'Jobs Details',
items: rows })
}
});
});
app.listen(3000);
This is the error
pp.post('/post', (request, response) => {
var description = request.body.description;
var contact_number = request.body.contact_number;
var city = request.body.city;
var budget = request.body.budget;
var category = request.body.optradio;
var query = connection.query("insert into jobs(Jobs_id,Description,Category,City,Contact_number,Budget) values(?,?,?,?,?,?)", [null, description, category, city, contact_number, budget],
function (err) {
if (err) {
console.log(err);
} else {
response.redirect('/data');
}
});
});
app.get('/data', function (request, response) {
connection.query("SELECT * FROM jobs ORDER BY Jobs_id DESC", (err, rows, fields) => {
if (err) {
console.log(err);
}
else {
response.render('feed', {
title: 'Jobs Details',
items: rows
})
}
});
});
app.listen(3000);
There can be only one response to single HTTP request. In your code, you are first trying to send response with
response.send("successful");
but this on its own doesn't break the flow of the function which means that if the condition is actually met then this will execute and the execution continues and finds another response, in this case
response.redirect('/data');
and it will try to send another response to the original http request but at this point it is already too late because one response has already been send.
To solve this issue in general, you can place return in front of any line of code that is closing the the connection (response.send, response.redirect, ...). That way, the function's execution is terminated at the first response, whichever it is.
So you could do something like
var query=connection.query("insert into jobs(Jobs_id,Description,Category,City,Contact_number,Budget) values(?,?,?,?,?,?)",[null,description,category,city,contact_number,budget],function(err){
if(err)
console.log(err);
else
return response.send("successful");
});
return response.redirect('/data');
});

Fetch from multiple, separate, collections with Express and MongoDB

I have a site where i need some data from my Mongo data to be shown. My problem, however, is that i need data from two collections. Collections that are completely separate and have nothing to do with each other.
Right now i have this in my routes for my profile-page:
router.get('/profile', function(req, res,next) {
var resultArray = [];
mongo.connect(url, function(err, db) {
var cursor = db.collection('users').find();
cursor.forEach(function(doc, err) {
resultArray.push(doc);
}, function() {
db.close();
res.render('profile/index', {users: resultArray});
});
});
});
And this, of course, works perfectly fine. But how do i get a second db.collection('colors').find(); to be passed along to my template too?
I'm sure it's something trivial, and me just not quite having the full grasp of things, but yeah.. I'm stuck..
Use the async library which is best suited for this scenario. Where you need to run multiple tasks that do not depend on each other and when they all finish do something else, you should use async.parallel() method. The signature is async.parallel(tasks, callback), where tasks is an array of functions.
It will immediately run all the functions in parallel, wait for all of them to call their task callback, and finally when all tasks are complete it will run callback (the final callback).
The following example demonstrates how this could be adapted for your use case:
router.get('/profile', function(req, res, next) {
mongo.connect(url, function(err, db) {
var locals = {};
var tasks = [
// Load users
function(callback) {
db.collection('users').find({}).toArray(function(err, users) {
if (err) return callback(err);
locals.users = users;
callback();
});
},
// Load colors
function(callback) {
db.collection('colors').find({}).toArray(function(err, colors) {
if (err) return callback(err);
locals.colors = colors;
callback();
});
}
];
async.parallel(tasks, function(err) { //This function gets called after the two tasks have called their "task callbacks"
if (err) return next(err); //If an error occurred, let express handle it by calling the `next` function
// Here `locals` will be an object with `users` and `colors` keys
// Example: `locals = {users: [...], colors: [...]}`
db.close();
res.render('profile/index', locals);
});
});
});
Try this code:
router.get('/profile', function(req, res,next) {
var resultArray = {
users : [],
colors : []
};
mongo.connect(url, function(err, db) {
var cursor = db.collection('users').find();
cursor.forEach(function(doc, err) {
resultArray.users.push(doc);
}
var colors = db.collection('colors').find();
colors.forEach(function(doc,err){
resultArray.colors.push(doc);
}, function() {
db.close();
res.render('profile/index', {users: resultArray.users, colors: resultArray.colors});
});
});
});
Didn't have time to check it, but I'm pretty sure that it would work.

nodejs: Async and find issues

I have an array, and for each row I need to do findIfExist and save into mongodb. The code is here:
router.post('/namespaceUpload', function(req, res,next) {
var data=req.body;
var totalRows=data.allRows.length;
var conceptObject ={};
var existingConcept;
for (var i=0;i<totalRows;i++){
async.series([
conceptPrepare,
conceptFind,
conceptSave,
], function (err, result) {
console.log('kraj');
res.json('Ok');
});
}
function conceptPrepare(callback){
conceptObject.name= data.allRows[i].name;
conceptObject.user= data.userId;
callback();
}
function conceptFind(callback){
namespaces.find({name: conceptObject.name}, function(err, result) {
if (err)
next(err);
else {
if (result.length==0){
console.log('0');
existingConcept='';
} else {
console.log(result.length);
existingConcept=result[0];
}
}
callback();
});
}
function conceptSave(callback){
var namespace = new namespaces();
if (existingConcept==''){
namespace.name=conceptObject.name;
namespace.description=conceptObject.description;
namespace.lastUpdate.user=conceptObject.user;
namespace.save(function(err) {
if (err)
return next(err);
callback();
})
}
}
So I Used async.series, but only last record is written in database as much times as many array members i have. Also, I get an error " Can't set headers after they are sent." Any idea?
You're getting the Can't set headers after they are sent error message because you 're not allowed to return smtg eg : res.send,res.render more than one time but in your for loop, it goes totalRows times
try to return one value at the end of the loop

rest api using express.js and PostgreSQL

I have a script that has rest apis that gets data from a postgresql database and returns it back to the client. At the start, the script only uses the about 7mb of memory and the response time when making queries is very fast. However, as time passes by(about 1 day), the memory used by the script balloons to 170mb. And now, the queries takes more than 1 minute to respond. But when I restart the script, it is now again fast on its response. I am clueless as to why this happens. Can anybody shed light on this? Here is a portion of what my script looks like:
var port = process.env.PORT || 8000;
var router = express.Router();
router.get('/:id/from/:prevdate', function (req, res) {
var results = [];
var id = req.params.id;
var prevdate = req.params.prevdate;
pg.connect(connectionString, function (err, client, done) {
var query = client.query("some sql statement here", [id, prevdate]);
query.on('row', function (row) {
results.push(row);
});
query.on('end', function () {
client.end();
return res.json(results);
});
if (err) {
console.log(err);
}
});
});
router.get('/:id/getdata', function (req, res) {
var results = [];
var id = req.params.id;
pg.connect(connectionString, function (err, client, done) {
var query = client.query("some sql statement here", [id]);
query.on('row', function (row) {
results.push(row);
});
query.on('end', function () {
client.end();
return res.json(results);
});
if (err) {
console.log(err);
}
});
});
app.use('/restapitest', router);
app.listen(port);
console.log('Webservice started using port: ' + port);
You are mixing connection pooling (which uses done()) with creating single connections (which uses client.end()).
Try this:
query.on('end', function() {
done();
return res.json(results);
});
Also, since you are storing all results in memory anyway, there's no need to use events. So with proper error and connection handling, you could use this:
pg.connect(connectionString, function (err, client, done) {
var sendError = function(err) {
console.log(err);
return res.sendStatus(500);
};
if (err) return sendError(err);
client.query("some sql statement here", [id, prevdate], function(err, results) {
// Done with the client.
done();
// Handle any errors.
if (err) return sendError(err);
// Return result
return res.json(results);
});
});

get the last updated mongo id from nodejs

am working on push notifications using mongodb and nodejs.
I can see the newly added notifications (which are addede in Mongodb) in my browser
But, if I updated the record, the value is not updating in the browser
// if no error get reference to colelction named: 'notifications'
db.collection('notifications', function(err, collection){
if(err) {
throw err;
}
// if no error apply a find() and get reference to doc
collection.find().sort({
$natural: -1
}).limit(1).nextObject(function(err, doc) {
// Rewind the cursor, resetting it to point to the start of the query
if(err) {
throw err;
}
// using tailable cursor get reference to our very first doc
var query = {
_id: {
$gt: doc._id
}
};
var options = {
tailable: true,
awaitdata: true,
numberOfRetries: -1
};
var cursor = collection.find(query, options).sort({
$natural: 1
});
// This function will take cursor to next doc from current as soon as 'notifications' database is updated
function next() {
cursor.nextObject(function(err, message) {
if (err) throw err;
console.log(message.message);
mdsok.volatile.emit('notification', message);
next();
});
}
// what you need to do is: call it first time
next();
});
This is what i am doing in my code.
what should I do to update the value in the browser when I update the same in db.
Please help me . Thanks in advance!
My problem was solved upto some extent.
var http = require('http'),
fs = require('fs'),
// NEVER use a Sync function except at start-up!
index = fs.readFileSync('index.html');
// Send index.html to all requests
var app = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.end(index);
});
// Socket.io server listens to our app
var io = require('socket.io').listen(app);
var MongoClient = require('mongodb').MongoClient;
function getdata(){
MongoClient.connect("mongodb://127.0.0.1:27017/test", function(err, db) {
var collection = db.collection('my_collection');
var stream = collection.find({
//'_id': new ObjectID('53eb6f2e75fd7ad00d000029')
//_id: ObjectID.createFromHexString("53eb6f2e75fd7ad00d000029")
}).stream();
stream.on("data", function(item) {
io.sockets.emit('db_status', {
status: item.status
});
prev = item.status;
console.log(prev);
});
stream.on("end", function() {
console.log("Done loading data");
});
});
}
// Send current time every 5 secs
setInterval(getdata, 5000);
// Emit welcome message on connection
io.sockets.on('connection', function(socket) {
socket.emit('welcome', {
message: 'Welcome!'
});
socket.on('i am client',function(data){
console.log(data);
});
});
app.listen(3000);
for every 5 secs, i am hitting the db and getting the value and displaying it in the browser.
To get the newly inserted object, we are using .nextObject() in node.js
Is there any way to get the updated object of the db as above in node.js.

Resources