I'm working on a Node.js server, connecting to MongoDB and written with TypeScript. When I try to use MongoDB it doesn't create a connection, however when I check the mongo output it does appear to create a connection.
What am I missing in my code to define the connection in Node.js?
My connection string is 'mongodb://localhost:27017'
My connection method:
connect() {
console.log('connecting to mongo') //this is called
MongoClient.connect(this.connectionString, {useNewUrlParser: true})
.then(client => {
console.log('setting client'); //this doesn't get called
this.client = client;
console.log(this.client);
})
.catch(error => {
console.log('error during connecting to mongo: '); //this also doesn't get called
console.error(error);
});
}
Mongo output:
2018-11-08T23:06:24.106+0100 I NETWORK [listener] connection accepted from 127.0.0.1:51345 #11 (2 connections now open)
2018-11-08T23:06:24.107+0100 I NETWORK [conn11] received client metadata from 127.0.0.1:51345 conn11: { driver: { name: "nodejs", version: "3.1.9" }, os: { type: "Darwin", name: "darwin", architecture: "x64", version: "17.7.0" }, platform: "Node.js v8.9.3, LE, mongodb-core: 3.1.8" }
My repository is at https://github.com/FrisoDenijs/MEAN-ToDo/blob/master/server/src/db/mongo.db.ts for the full code.
console.log(db)
as asked by shkaper
MongoClient {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
s:
{ url: 'mongodb://localhost:27017',
options:
{ servers: [Array],
caseTranslate: true,
useNewUrlParser: true,
socketTimeoutMS: 360000,
connectTimeoutMS: 30000,
promiseLibrary: [Function: Promise] },
promiseLibrary: [Function: Promise],
dbCache: {},
sessions: [] },
topology:
Server {
domain: null,
_events:
{ serverOpening: [Function],
serverDescriptionChanged: [Function],
serverHeartbeatStarted: [Function],
serverHeartbeatSucceeded: [Function],
serverHeartbeatFailed: [Function],
serverClosed: [Function],
topologyOpening: [Function],
topologyClosed: [Function],
topologyDescriptionChanged: [Function],
commandStarted: [Function],
commandSucceeded: [Function],
commandFailed: [Function],
joined: [Function],
left: [Function],
ping: [Function],
ha: [Function],
authenticated: [Function],
error: [Function],
timeout: [Function],
close: [Function],
parseError: [Function],
open: [Object],
fullsetup: [Object],
all: [Object],
reconnect: [Function] },
_eventsCount: 25,
_maxListeners: Infinity,
clientInfo:
{ driver: [Object],
os: [Object],
platform: 'Node.js v8.9.3, LE' },
s:
{ coreTopology: [Object],
sCapabilities: null,
clonedOptions: [Object],
reconnect: true,
emitError: true,
poolSize: 5,
storeOptions: [Object],
store: [Object],
host: 'localhost',
port: 27017,
options: [Object],
sessionPool: [Object],
sessions: [],
promiseLibrary: [Function: Promise] } } }
The issue is because mongo.connect
is async code and controller call it wrongly. so the subsequent line mongo.getDb()
will be executed without having this.client
initiated properly.
Since you use Typescript, we can use async/await
for cleaner code.
async connect() { // add async
console.log('connecting to mongo');
try {
if (!this.client) { // I added this extra check
console.log('setting client');
this.client = await MongoClient.connect(this.connectionString, { useNewUrlParser: true })
console.log(this.client);
}
} catch(error) {
console.log('error during connecting to mongo: ');
console.error(error);
}
}
And in controller code
async get(req: Request, res: Response) { // add async
const mongo = new MongoDb();
await mongo.connect(); // add await
const db = mongo.db();
// ....
}
I tried your repo with the changes and got this response
Hope it helps
Based on what you said about neither error nor success callbacks being called, I think the problem is not only in code here: https://github.com/FrisoDenijs/MEAN-ToDo/blob/master/server/src/db/mongo.db.ts
But also e.g. here: https://github.com/FrisoDenijs/MEAN-ToDo/blob/master/server/src/controllers/to-do.controller.ts
When you run mongo.connect
there should be an option to wait for the promise returned from MongoClient.connect
. So I would change code in mongo.db.ts
to for example sth like this (it depends how you want to handle this promise):
connect() {
console.log('connecting to mongo')
return MongoClient.connect(this.connectionString, {useNewUrlParser: true})
.then(client => {
console.log('setting client');
this.client = client;
console.log(this.client);
})
.catch(error => {
console.log('error during connecting to mongo: ');
console.error(error);
});
}
Then in to-do.controller.ts
you can await
this or use then
:
get(req: Request, res: Response) {
const mongo = new MongoDb();
mongo.connect().then(() => {
const db = mongo.getDb();
const collection = db.collection('todo', (error, collection) => {
if (error) {
res.json(error);
res.statusCode = HttpStatus.BAD_REQUEST
return;
}
collection.find().toArray((error, result) => {
if (error) {
res.json(error);
res.statusCode = HttpStatus.BAD_REQUEST
}
res.json(result);
res.statusCode = HttpStatus.OK;
})
});
mongo.close();
});
}
I suppose that your code just does not "wait" for connection to be established and then fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With