MongoDB-Express: Cannot get the client/db out of connect function - node.js

I am separating the connect function of MongoDB to a separate module, so that the mongoDB connection is reusable. The issue is, I could not get the client/DB variable outside the connect function. It shows undefined.
var MongoClient = require('mongodb').MongoClient;
var _client;
var mongoURL = "mongodb://localhost:27017/";
module.exports = {
connectToMongoServer: (callback) => {
MongoClient.connect(mongoURL,{ useNewUrlParser: true },function(err,client){
_client = client;
return callback(err);
});
},
getClient: () => {
return _client;
}
};
Within the connect function, the _client details contains the information, but if I return it using getClient, it shows undefined.
MongoDB - v3.6.5
Node - v9.9.0

I've made up a snippet which should work the same ad your code, and it works.
So I think the problem is how you are calling your function getClient(); are you sure you are calling it after it get connected?
var _client;
function someAsyncFunc(callback) {
setTimeout(() => callback(false, 'client'), 500);
}
const file = {
connectToMongoServer: (callback) => {
someAsyncFunc(function(err, client) {
_client = client;
return callback(err);
});
},
getClient: () => {
return _client;
}
};
console.log('display one :', file.getClient());
file.connectToMongoServer((err) => {
console.log('display error :', err);
console.log('display two :', file.getClient());
});

Related

Not able to return value from promise in Nodejs

I have written the following code in Nodejs which is saving data in MongoDB:
function insertDoc(db,data){
return new Promise(resolve => {
callback=db.collection('AnalysisCollection').insertOne(data).then(function(response,obj){
console.log("Inserted record");
resolve(obj);
//console.log(obj);
// response.on('end',function(){
// resolve(obj);
// });
//return resolve(obj);
}).then(() => { return obj }
).catch(function(error){
throw new Error(error);
});
})
}
I am calling the above function from the main function like this:
async function cosmosDBConnect(nluResultJSON){
try{
//console.log("Inserting to cosmos DB");
console.log(nluResultJSON);
var url = config.cosmos_endpoint;
var result="";
var data = JSON.parse(JSON.stringify(nluResultJSON));
MongoClient.connect(url, function(err, client) {
assert.equal(null, err);
var db = client.db('NLUAnalysisDB');
// insertDoc(db, data, function() {
result=insertDoc(db, data, function() {
console.log(result);
client.close();
//return data._id;
});
});
}
catch (e) {
console.log(e);
}
}
module.exports = { cosmosDBConnect };
But in cosmosDBConnect, I am getting 'undefined' for the result, though in insertDoc I am getting the output for'obj' with _id for the inserted record.
Please help me to return this _id to cosmosDBConnect.
You are use callbacks inside of async function, which creates internal scopes. So your return aplies to them instead of whole function. You should use Promise-based methods inside of async function using await (without callbacks) or wrap whole function into own Promise otherwise.
Example:
function cosmosDBConnect(nluResultJSON) {
return new Promise((resolve, reject) => {
var url = config.cosmos_endpoint;
var result = '';
var data = JSON.parse(JSON.stringify(nluResultJSON));
MongoClient.connect(url, function(err, client) {
if (err) return reject(err);
assert.equal(null, err);
var db = client.db('NLUAnalysisDB');
insertDoc(db, data).then(obj => {
console.log(obj);
client.close();
return resolve(data._id);
});
});
});
}
Also you need to understand that your insertDoc return Promise and do not accept callback you tried to pass.
Ref: async function
result = insertDoc(db, data).then((data) => {
console.log(data);
}).catch(err => console.error(err));

I am getting UnhandledPromiseRejectionWarning error when trying to connect node js with mongoDB Atlas cloud

I created a app.js file and there I am trying to connect with mongoDB atlas. The error 'UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()' is throwing when I run in terminal.
const connect = async function () {
const MongoClient = require('mongodb').MongoClient;
const uri = "mymongoDB atals url for nodejs";
MongoClient.connect(uri, { useNewUrlParser: true });
const collection = client.db("feedback").collection("itinerary");
// perform actions on the collection object
client.close();
};
connect().then(() => {
console.log('handle success here');
}).catch((exception) => {
console.log('handle error here: ', exception)
})
Try putting the async function operations in try catch block as below. I hope this should do the work.
const connect = async function () {
try {
const MongoClient = require('mongodb').MongoClient;
const uri = "mymongoDB atals url for nodejs";
MongoClient.connect(uri, { useNewUrlParser: true });
const collection = client.db("feedback").collection("itinerary");
// perform actions on the collection object
client.close();
} catch (e) {
console.log("Error", e)
}
};
connect().then(() => {
console.log('handle success here');
}).catch((exception) => {
console.log('handle error here: ', exception)
})
Try this:
const MongoClient = require('mongodb').MongoClient;
const connect = function () {
return new Promise((resolve, reject) => {
try {
const uri = "mymongoDB atals url for nodejs";
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
if (err) {
reject(err)
}
const collection = client.db("feedback").collection("itinerary");
client.close();
resolve();
});
} catch (e) {
reject(e);
}
})
};
connect().then(() => {
console.log('handle success here');
}).catch((exception) => {
console.log('handle error here: ', exception)
})
Try this approach:
const MongoClient = require('mongodb').MongoClient;
// replace the uri string with your connection string.
const uri = "mymongoDB atals url for nodejs"
MongoClient.connect(uri, function(err, client) {
if(err) {
console.log('handle error here: ');
}
console.log('handle success here');
const collection = client.db("feedback").collection("itinerary");
// perform actions on the collection object
client.close();
});
Try by wrapping all the content of your function in a try/catch block:
const connect = async function () {
try {
const MongoClient = require('mongodb').MongoClient;
const uri = "mymongoDB atals url for nodejs";
MongoClient.connect(uri, { useNewUrlParser: true });
// most probably this is throwing the error. Notice the extra await
const collection = await client.db("feedback").collection("itinerary");
// perform actions on the collection object
client.close();
} catch (e) {
console.log(`Caught error`,e)
}
};
connect().then(() => {
console.log('handle success here');
}).catch((exception) => {
console.log('handle error here: ', exception)
})

In node pg client.query doesn't return

I am currently updating a very old application to run on Heroku. I've had to update to the latest version of pg to support the latest postgres on heroku. However, this was originally abstracted out so it's all handled in the one file (below). I can connect to the DB successfully but client.query never returns.
The first console.log is SELECT * FROM public.user WHERE "email" = $1 [ 'xx#xx.com' ]. However, I never reach the second console.log. I get no connection errors.
I am using pg 7.x and postgres 10.
Any ideas?
const { Client } = require('pg');
const config = require('.././app/models/config.js');
const client = new Client({
connectionString: process.env.DATABASE_URL || config.database || ''
});
var conString = config.database || '';
client.connect();
module.exports = {
query: function(text, values, cb) {
console.log(text, values);
client.query(text, values, function(err, result) {
console.log(err, result);
if (err) {
console.log(err);
}
if (cb) {
cb(err, result);
}
client.end();
});
}
};
EDIT: I've edit with the correct promise from pg. Due the asynchronous nature of Nodejs you have to work with promises, something like:
module.exports = {
query: function(text, values) {
console.log(text, values);
return new Promise(function (resolve, reject) {
client.query(text, values)
.then(function (res) { resolve(res.rows[0]) })
.catch(function (e) { reject(e.stack) };
});
}
};
Then require you module and consume the promise:
var myPrevModule = require('module');
myPrevModule.query.then(function(resp){
// Consume the callback here ...
}).catch(function(err){
console.error(err);
})

Check if mongoDB is connected

I have mongoDB in my app.
I want to check if mongoDB is connected, before I listen to the app.
Is it the best way for doing it?
This is my server.js file:
var express = require('express');
var mongoDb = require('./mongoDb');
var app = express();
init();
function init() {
if (mongoDb.isConnected()) {
app.listen(8080, '127.0.0.1');
}
else {
console.log('error');
}
}
isConnected runs getDbObject.
getDbObject connects to mongoDB and returns an object:
connected (true/false), db (dbObject or error).
Then, isConnected resolve/reject by connected property.
This is mongoDb.js file:
//lets require/import the mongodb native drivers.
var mongodb = require('mongodb');
// Connection URL. This is where your mongodb server is running.
var url = 'mongodb://localhost:27017/myDb';
var connectingDb; // promise
//We need to work with "MongoClient" interface in order to connect to a mongodb server.
var MongoClient = mongodb.MongoClient;
init();
module.exports = {
isConnected: isConnected
}
// Use connect method to connect to the Server
function init() {
connectingDb = new Promise(
function (resolve, reject) {
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
reject(err);
}
else {
console.log('Connection established to', url);
//Close connection
//db.close();
resolve(db);
}
});
}
);
}
function getDbObject() {
return connectingDb().then(myDb => {
return {
connected: true,
db: myDb
}
}
)
.catch(err => {
return {
connected: false,
db: err
}
}
)
}
function isConnected() {
return new Promise(
function(resolve, reject) {
var obj = getDbObject();
if (obj.connected == true) {
console.log('success');
resolve(true);
}
else {
console.log('error');
reject(false);
}
}
)
}
Any help appreciated!
there are multiple ways depends on how your DB is configured. for a standalone (single) instance. You can use something like this
Db.connect(configuration.url(), function(err, db) {
assert.equal(null, err);
if you have a shared environment with config servers and multiple shards you can use
db.serverConfig.isConnected()
Let client be the object returned from MongoClient.connect:
let MongoClient = require('mongodb').MongoClient
let client = await MongoClient.connect(url ...
...
This is how i check my connection status:
function isConnected() {
return !!client && !!client.topology && client.topology.isConnected()
}
This works for version 3.1.1 of the driver.
Found it here.
From version 3.1 MongoClient class has isConnected method. See on https://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html#isConnected
Example:
const mongoClient = new MongoClient(MONGO_URL);
async function init() {
console.log(mongoClient.isConnected()); // false
await mongoClient.connect();
console.log(mongoClient.isConnected()); // true
}
init();
There has been some changes since version 3, isConnected is no longer available in version 4. The correct way of dealing with an ambiguous connection is to just call MongoClient.connect() again. If you're already connected nothing will happen, it is a NOOP or no-operation, and if there is not already a connection you'll be connected (as expected). That said, if you really want to know if you have a connection try something like this:
const isConnected = async (db) => {
if (!db) {
return false;
}
let res;
try {
res = await db.admin().ping();
} catch (err) {
return false;
}
return Object.prototype.hasOwnProperty.call(res, 'ok') && res.ok === 1;
};

error connecting to mongodb on Nodejs

I am trying to connect to mongodb from node and I am getting below error
node_modules\mongodb\lib\mongo_client.js:458
throw err
^
ReferenceError: connect is not defined
I am using the mongodb module version
2.0.48
I am trying to run a simple test code
(function (dbase) {
var mdb = require('mongodb');
var mongoUrl = "mongodb://localhost:27017/theBoard";
var connection;
dbase.dbConnection = function (next) {
if (connection) {
next(null, connection);
} else {
mdb.MongoClient.connect(mongoUrl, function(err, db) {
if (err) {
next(err, null);
} else {
console.log("connected");
connection = { db: db , notes: db.collection("notes")};
next(null, connection);
}
});
}
}
Can someone please help me understand this issue.
---Additional information
data module -
(function (data) {
var mdb = require('./db.js');
data.GetCategory = function() {
mdb.dbConnection(function(err, db) {
if (err)
console.log("Error connecting to mango");
if (connect) {
db.notes.count(function(err, count) {
if (err)
console.log("Failed to retreive collection");
else
console.log("Count - "+count);
});
console.log("Connected");
}
});
}})(module.exports);
db.js
(function (dbase) {
var mdb = require('mongodb');
var mongoUrl = "mongodb://localhost:27017/theBoard";
var connection;
dbase.dbConnection = function (next) {
if (connection) {
next(null, connection);
} else {
mdb.MongoClient.connect(mongoUrl, function(err, db) {
if (err) {
next(err, null);
} else {
console.log("connected");
connection = { db: db , notes: db.collection("notes") };
next(null, connection);
}
});
}
} })(module.exports);
Controller -
(function (controller) {
var data = require('.././data');
controller.init = function (app) {
app.get("/", handleRequest);
}
var handleRequest = function (req, res) {
data.GetCategory();
var a = {};
a.send = "Mamma is coming home";
res.send(a);
}
})(module.exports);
Just in case some one runs into an issue like this due to bad coding practice even if it for test purpose is to never have function names which are the same as the function names in the API. In db.js I had an undefined variable named connect which trowing and error when it was accessed and since it was called through the API function called "connect" the error was thrown by the API leading me to believe that the API function had an issue

Resources