I cannot seem to get the last callback (commented as "optional callback") called to send the result back to the browser. Any pointers as to what I am doing wrong? I am using the following modules: async, restify and postgresql for node.js
console.log('Start');
var async = require('async');
var restify = require('restify');
var server = restify.createServer();
server.use(restify.bodyParser());
server.get('/user/creationdate/:username', function(req, res, next) {
var userName = req.params.username;
var record;
async.parallel([
function(callback){
getUserByName(userName, function(err, user) {
if (err) return callback(err);
record = user;
});
}
],
// optional callback
function(err){
console.log('5. Following record has been retrieved:' + record);
res.send(record);
});
next();
});
server.listen(8080, function () {
console.log('%s listening at %s', server.name, server.url);
});
handleError = function handleError(err) {
if(!err) { return false; }
else {
console.log('The following error occurred:' + err);
}
return true;
};
function getPgClient(){
var pg = require('pg');
var client = new pg.Client({
user: 'postgres',
password: 'password',
database: 'foobar',
host: '192.168.1.100',
port: 5432
});
client.on('drain', client.end.bind(client)); //disconnect client when all queries are finished
return client;
}
function getUserByName(userName, callback){
var client = getPgClient();
console.log('2. Trying to connect to DB');
client.connect(function(err) {
console.log('3. Error connecting to DB:' + handleError(err));
if(handleError(err)) return callback(err);
client.query("SELECT created_at FROM users WHERE username='" + userName + "'", function(err, result) {
if(handleError(err)) return;
console.log('4. Error occurred:' + err);
console.log(result);
console.log(callback);
callback(null, result);
})
});
}
I'm not sure why you're using async since you're only calling one asynchronous function. But the reason your callback isn't called is because you're not ending the first function by calling its callback:
async.parallel([
function(callback) {
getUserByName(userName, function(err, user) {
// call async callback with err and user
callback(err, user);
});
}
], function(err, record) {
console.log('5. Following record has been retrieved:' + record);
res.send(record);
});
Or, shorter:
async.parallel([
function(callback) {
getUserByName(callback);
}
], function(err, record) {
console.log('5. Following record has been retrieved:' + record);
res.send(record);
});
Or, in this case, even shorter (and without the need for async):
getUserByName(function(err, record) {
// handle error, or ...
console.log('5. Following record has been retrieved:' + record);
res.send(record);
});
Saw my mistake, missing the line where I should have returned the callback as in:
async.parallel([
function(callback){
getUserByName(userName, function(err, user) {
if (err) return callback(err);
record = user;
return callback(null, record);
});
}
Related
I am trying to get the count of the documents in MongoDB collection but I am not getting the count.
Here's what I am trying:
//get the invoice count
Routes.route('/invoicescount').get((req, res) => {
invoicesDB.count({}, (err, count) => {
if (err) {
res.status(400).send(err);
} else {
const c = count;
res.status(200).send(c);
}
});
});
It doesn't give any value but in the console it gives this error:
error found: CastError: Cast to ObjectId failed for value
"invoicescount" at path "_id" for model "invoices"
i am using this function for getting the count of every collection:
var MongoClient = require('mongodb').MongoClient;
var dbName = "myName";
var port = "27017";
var host = "localhost";
function getNumOfDocs (collectionName, host, port, dbName, callback) {
MongoClient.connect("mongodb://" + host + ":" + port + "/" + dbName, function (error, db){
if(error) return callback(error);
db.collection(collectionName).count({}, function(error, numOfDocs){
if(error) return callback(error);
db.close();
callback(null, numOfDocs);
});
});
}
and i call it:
getNumOfDocs("collName", host, port, dbName, function(err, count) {
if (err) {
return console.log(err.message);
}
console.log('number of documents', count);
});
Trying to call database query from other javascript file in NodeJS.
Sample database file:
function addUser(user) {
connection.connect(function (err) {
if (err) {
console.error('Error connecting: ' + err);
}
console.log('Connected as id ' + connection.threadId);
});
var sql = "INSERT INTO `mobile`.`main` (`userId`) VALUES (?);"
var inserts = [user];
connection.query(sql, inserts, function (error, results) {
console.log('query');
if (error) {
return error;
} else {
console.log('Success Query');
return results;
}
});
connection.end(function (err) {
if (err) {
console.error('Error connecting: ' + err);
}
console.log('Connection closed!');
});
}
module.exports = addUser;
Sample main.js file:
app.get('/api/mysql/:user', function (req, res) {
var user = req.params.user;
addUsers(user)
res.json({
SQLResp: 'Query succes',
result: addUsers.result
});
});
How to get the result from the first file and use it as a response in the main js?
Welcome to stack overflow.
this is missing from your database file, How did you got connection there?
Here's a sample example over How to export database connection and use this to make calls from other files.
Also do read about callbacks-functions, Promises, async-await and Asynchronous functions of JavaScript. These are basics of JavaScript and also do go through NodeJS docs.
DB.js:
const MYSQL = require('mysql');
const connection = MYSQL.createConnection({
host: 'localhost', // url of db
user: 'root',
password: 'root',
database: 'dbName'
});
module.exports = connection;
Now will use this connection from other file to call database.
app.js:
const db = require('./DB'); // Path of your db connection file. I named it DB.js on same level as of app.js
function addUser(user) {
// Since database calls are async in NodeJS thus using promises.
return new Promise ( (resolve, reject) => {
db.connect(function (err) {
if (err) {
console.error('Error connecting: ' + err);
return reject(err);
}
console.log('Connected as id ' + connection.threadId);
});
var sql = "INSERT INTO `mobile`.`main` (`userId`) VALUES (?);"
var inserts = [user];
db.query(sql, inserts, function (error, results) {
console.log('query');
if (error) {
return reject(err);
} else {
console.log('Success Query');
return resolve(results);
}
});
db.end(function (err) {
if (err) {
console.error('Error connecting: ' + err);
}
console.log('Connection closed!');
});
});
}
app.get('/api/mysql/:user', function (req, res) {
var user = req.params.user;
addUsers(user)
.then (result => { // When addUsers will resolve promise will be in then.
res.json({
SQLResp: 'Query succes',
result: result
});
})
.catch(err => { // If promise is rejected then on catch
res.json({
SQLResp: 'Query err',
result: err
});
});
});
You need to pass a callback into your addUser function, and call it inside your connection.query with the results.
Currently, when you return, you're returning inside another callback, which means the data is more or less being thrown away.
That will also let you handle all of the error cases in a way you can tell the user about.
file ConnectToDB
var pg = require("pg");
var dataWithDB = require('./DataBase/ConnectToDb');
var pool = new pg.Pool({
host: "localhost",
port: "5432",
user: "postgres",
password: "111111",
database: "hrs"
});
pool.connect(function (err,client,done) {
if(err)console.log("connect " + err.toString());
else
client.query('SELECT id, "idName", "idContact", "idExperience",
"idSkill", "dateAdded", "dateColloquy"' +
'FROM public."applicant ";',function (err,result) {
if(err) {
//console.log("query " + err.toString());
exports.res = "Data NOT";
}
else {
console.log(result.rows);
module.exports.resul = result.rows;
}
done();
});
});
pool.end()
file app.js
var dataWithDB = require('./DataBase/ConnectToDb');
console.log(dataWithDB + " wit DB");
as a result deduces to me undefined wit DB
but should data from db
Can an error in the scope?
Data is sent if you specify at the end of the file module.exporst.result = "Example".
You should encapsulate your connect to db code in a function which takes a callback.
Here is an example, hopefully you get the idea. :)
./DataBase/ConnectToDb
var pg = require("pg");
module.exports = (callback) => {
var pool = new pg.Pool({
host: "localhost",
port: "5432",
user: "postgres",
password: "111111",
database: "hrs"
});
pool.connect(function (err, client, done) {
if (err) {
console.log("connect " + err.toString());
} else {
let query = 'SELECT id, "idName", "idContact",' +
' "idExperience","idSkill", "dateAdded", "dateColloquy"' +
'FROM public."applicant ";'
client.query(query, function (err, result) {
if (err) {
//console.log("query " + err.toString());
exports.res = "Data NOT";
callback(err);
}
else {
console.log(result.rows);
callback(null, result);
}
done(); // Not sure what this does! :-o
});
}
});
// Is this trying to close it before we've connected?
// It should probably be up above...
pool.end()
}
app
var connectToDb = require('./DataBase/ConnectToDb');
connectToDb((err, result) => {
// This is a callback!
if(err) console.log(err)
else console.log(result)
})
Do a google search for: node.js callback pattern
Here is what you should do: import a different callback function that you pass into your query. This callback will do whatever you want with result. As written, your method will not work and does not make sense.
I have a MongoDB connect call that crashes a heroku app..
I have been editing what was originally localHost code (was working perfectly) to work with Heroku MongoDb addons (like MongoLab), but how do I get someDBcollectionVariable to work with someDBcollectionVariable.find()
//MongoDB
var mongodb = require('mongodb');
var db;
var MONGODB_URI = process.env.MONGOLAB_URI;
var PORT = process.env.PORT;
var testColl;
function dbConnect() {
return mongodb.MongoClient.connect(MONGODB_URI, function(err, database) {
if(err) throw err;
db = database;
var testColl = db.collection('test');
app.listen(PORT);
console.log('Listening on port ' + PORT);
return testColl;
});
}
//calls then look like
app.post('/add', function (req, res) {
testColl.insert(
{
"title" : req.body.title,
"quantity" : parseInt(req.body.quantity)
},
function (err, doc) {
getAll(res);
});
});
//and getAll looks like this
function getAll(res) {
testColl.find().sort( { value: 1 } ).toArray(function (err, docs) {
res.json({docs: docs});
});
}
Before moving that code inside dbConnect(), testColl.find.. was generating a ResponseError because the connect code was completing before the variable could be set?
Returning a value from an asynchronous function makes no sense. To use the a value, you need to pass it to a callback function. The same goes for errors (you can't throw asynchronously). A fixed version of your code could look like:
//MongoDB
var mongodb = require('mongodb');
var db;
var MONGODB_URI = process.env.MONGOLAB_URI;
var PORT = process.env.PORT;
var testColl;
function dbConnect(callback) {
mongodb.MongoClient.connect(MONGODB_URI, function (err, database) {
if (err) {
return callback(err);
}
db = database;
database.collection('test', function (err, testColl) {
if (err) {
return callback(err);
}
app.listen(PORT);
console.log('Listening on port ' + PORT);
callback(null, testColl);
});
});
}
//calls then look like
dbConnect(function (err, testColl) {
if (err) {
return console.error(err.stack || err.message);
}
testColl.find...
});
I'm trying to do a login function but the Error: Can't set headers after they are sent is keep showing up in my terminal, based on my understanding this error is causing by res but I can't find the error in my code..
this is what I have so far:
login function
this.handleLoginRequest = function(req, res, next) {
"use strict";
var data = req.body;
users.validateLogin(data, function(err, user) {
"use strict";
if(err) {
res.send(400, err.message);
}else{
sessions.startSession(data, function(err, session_id) {
"use strict";
if (err) return next(err);
res.cookie('session', session_id);
res.send(200);
});
}
});
}
validateLogin function
this.validateLogin = function(data, callback) {
"use strict";
// Callback to pass to MongoDB that validates a user document
function validateUserDoc(err, user) {
"use strict";
if (err) return callback(err, null);
if (user) {
if (bcrypt.compareSync(data.password, user.password)) {
callback(null, user);
} else {
callback(new Error("Invalid password/email"), null);
}
}else{
// no such user error
callback(new Error("no such user"), null);
}
}
users.findOne({ '_id' : data.email }, validateUserDoc);
process.nextTick(function() {
callback(null, data);
});
}
It looks like the callback passed to validateLogin is called twice:
once from validateUserDoc;
once from the process.nextTick callback (that part seems to be some left-over code);