node.js res.json messed up - javascript

first i make a '/init' request and the response is {"x":50},
then i make a '/user' request and the response is {"x":50,"data":"jack"}. No problem so far, but if i make an init request again it makes a {"x":50,"data":"jack"} response again, how is this possible?
var resp.success = {"x":50}
exports.init = function (req, res) {
res.json(resp.success)
};
exports.user = function (req, res) {
User.findOne({_id: "1234"}).exec(function (err, user) {
var response = resp.success;
response.data = user.name;
res.json(response);
});
};

Because you've defined var resp.success = {"x":50} in a scope outside the #init and #user methods, when you modify/read the resp.success from within those methods, they are accessing a single shared object instance of resp.success. You can fix this by defining resp.success independently inside the #init method and #user:
exports.init = function (req, res) {
var resp.success = {"x":50}
res.json(resp.success)
};
exports.user = function (req, res) {
var resp.success = {"x":50}
User.findOne({_id: "1234"}).exec(function (err, user) {
var response = resp.success;
response.data = user.name;
res.json(response);
});
};
If you use the underscoreJS library, you could also do something like this:
var resp.success = {"x":50}
exports.init = function (req, res) {
var successResponseForThisRequest = _.clone(res.success);
res.json(resp.success)
};
exports.user = function (req, res) {
User.findOne({_id: "1234"}).exec(function (err, user) {
var successResponseForThisRequest = _.clone(res.success);
response.data = user.name;
res.json(response);
});
};

Related

Send a JSON array as response from Node.js

I am fetching data from a MongoDB database then putting it in a cursor to send that as a Node.js response.
var router = express.Router();
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
/* GET users listing. */
router.get('/', function(req, res, next) {
//res.send('respond with a resource');
MongoClient.connect(url, function(err, db) {
var cursor = db.collection('Employee').find();
cursor.each(function(err, doc) {
console.log(doc);
arrayres = doc ;
res.send(doc);
});
db.close();
});
});
module.exports = router;
It sends only the first record then I get this error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot remove headers after they are sent to the client
at ServerResponse.removeHeader (_http_outgoing.js:528:11)
at ServerResponse.send
Notice: I get this error only when there are multiple records to send as response.
You are sending the response twice. Which is impossible ( look at Why can't we do multiple response.send in Express.js? )
res.send('respond with a resource');
Here and
res.send(arrayres);
Here.
Here is a working example based on jeremy's answer :
router.get('/', function (req, res, next) {
MongoClient.connect(url, function (err, db) {
var cursor = db.collection('Employee').find();
let employees = []
const pushData = async () => {
cursor.forEeach( function (doc) {
employees.push(doc);
});
}
const sendResponse = async () => {
await pushData();
res.json(employees);
}
});
});
You can only send back one response to the browser (be it res.send(), res.end(), res.sendFile(), res.json() or any other). So, you can't have that inside a .forEach().
First, build an array, then send your data back once.
router.get('/', function (req, res, next) {
MongoClient.connect(url, function (err, db) {
var cursor = db.collection('Employee').find();
let employees = []
cursor.forEeach( function (doc) {
employees.push(doc);
});
res.json(employees);
});
});
Or with Mongoose :
Employee.find().lean().exec( (err,docs) => res.json(docs))

How do I use a callback to fetch data from mysql with node.js and ejs?

I need to fetch foo from the query below:
exports.get = function(id, cb) {
sql = 'SELECT `sidebar`, `test` FROM users WHERE `id` = "' + id + '"';
con.query(sql, function(err, foo) {
if (err) { return cb(err) }
else { return cb(foo) };
});
}
Then render foo on my app.js like this:
app.get('/dashboard', ensureLoggedIn('/login'),
function(req, res) {
const id = req.session.passport.user;
const foo = db.defaults.set(id) //db.defaults.set calls the query
console.log(foo); //prints undefined
res.render('dashboard', { foo:foo });
});
This was my latest attempt:
app.get('/dashboard', ensureLoggedIn('/login'),
function(req, res, next) {
const id = req.session.passport.user;
db.defaults.get(id, function(err, foo) {
if (err) return next(err);
res.render('dashboard', {foo:foo});
//also tried:
//return res.render('dashboard', {foo:foo});
});
The attempt above doesn't render the page at all. The html loads as:
[object object]
What am I missing?
You're trying to render server side a template asynchronously (after fetching the data) and you can't do that.
What you can do is send synchronously the template to the client and then expose an endpoint to fetch those data and modify the page accordingly (on the client).
app.get('/dashboard', ensureLoggedIn('/login'), function(req, res) {
res.render('dashboard');
});
app.get('/fetchdata', function (req, res, next) {
const id = req.session.passport.user;
db.defaults.get(id, function(err, foo) {
if (err) return next(err);
res.send(foo);
});
})

Node.js, wordpress,redis

I need to get data from Redis in node server and send it to a Wordpress layout. I tried the following, but data doesn't seem to get sent.
var express = require('express');
var app = express();
var redis = require('redis');
var client = redis.createClient(); //creates a new client
client.on('connect', function () {
console.log('connected');
});
data = [];
client.set(['first', 'Oleh']);
client.set(['second', 'Ivan']);
client.set(['thirt', 'Andriy']);
client.set(['fourth', 'Olena']);
client.set(['fifth', 'Kristy']);
client.set(['sixth', 'Irina']);
client.get('first', function (err, reply) {
console.log(reply);
data.push(reply);
});
client.get('second', function (err, reply) {
console.log(reply);
data.push(reply);
});
client.get('thirt', function (err, reply) {
console.log(reply);
data.push(reply);
});
client.get('fourth', function (err, reply) {
console.log(reply);
data.push(reply);
});
client.get('fifth', function (err, reply) {
console.log(reply);
data.push(reply);
});
client.get('sixth', function (err, reply) {
console.log(reply);
data.push(reply)
});
app.get('http://localhost/wordpress/', function (req, res) {
res.type('application/json'); // set content-type
res.send(this.data); // send text response
console.log(this.data);
});
app.listen(process.env.PORT || 4730);
It seems you have the scope incorrect. this.data refers to the function (req, res) {} and not your global scope.
Try doing res.json(data) and remove the res.type(), as res.json already takes care of that for you.

Need a way to set res object after couchbase DB call "Error: Can't set headers after they are sent"

var express = require('express');
var search = express.Router();
search.get('/', function(req, res, next) {
console.log('1');
dbCall(function(error, result) {
if (error) {
res.status(404).json();
} else {
res.json(result);
}
});
console.log('last');
next();
});
var dbCall = function(callback) {
var couchbase = require('couchbase');
var cluster = new couchbase.Cluster('couchbase://127.0.0.1');
var bucket = cluster.openBucket('default');
var doc;
var ViewQuery = couchbase.ViewQuery;
var query = ViewQuery.from('dev_test', 'allData');
bucket.query(query, function(err, viewResults) {
if (err) {
callback(err, null);
} else {
console.log('inqueryCall');
var results = viewResults;
callback(null, results);
console.log(results);
}
});
};
module.exports = search;
Here's the error that I get is :
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
Can someone please explain the issue here(not just the solution)?
I've added console.log and the issue here is that the couchbase call to async
Remove next() call, that is causing this error. next() is used in middleware to pass the flow to next middleware or endpoint/route
search.get('/', function(req, res, next) {
dbCall(function(error, result) {
if (error) {
res.status(404).json();
} else {
res.json(result);
}
});
});

in node.js with express req.session is undefined inside my require() module

I'm wondering why req.session.username is undefined in the tag >>>DOESNT WORK<<< while it does work in the tag >>>THIS DOES WORK<<< . I brought in req as an argument to my module but it seems I'm supposed to do something else? The /ajax route is accessed via a ajax call and it does set the session variable in >>>THIS DOES WORK<<<
//index.js file
var express = require('express');
var router = express.Router();
var app = express();
var functions = require('../public/javascripts/functions.js');
router.post('/ajax', function(req, res , next){
var username = req.param("username");
var password = req.param("password");
var operation = req.param("operation");
else if (operation === "validate")
{
async.series([
function()
{
functions.validate(username, password, req);
}
], function(err,result)
{
if (err)
return console.log(err);
console.log(result);
});
//req.session.username = "yaryar"; >>>THIS DOES WORK<<<
}
var strings = ["rad", "bla", "ska"]
console.log('body: ' + JSON.stringify(req.body));
console.log("AJAX RECEIVED");
res.send(strings);
});
module.exports = router;
functions.js file:
module.exports = {
validate: function(username, password, req) {
var url = 'mongodb://localhost';
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
MongoClient.connect(url, function(err, db)
{
assert.equal(null, err);
console.log("Connected correctly to server.");
var cursor = db.collection('users').find({username : username});
cursor.each(function(err,doc,req)
{
assert.equal(err, null);
if (doc != null)
{
console.log("user found: " + doc.username);
req.session.username = "ttyy"; // >>>DOESNT WORK<<<
return true
}
else
{
console.log("user not found");
return false;
}
});
//db.close();
});
}
};
you're overwriting req by doing cursor.each(function(err,doc,req) change it to cursor.each(function(err,doc,arr) and it will work

Categories