Home > Back-end >  mongoose.connection.once('open') callback never firing
mongoose.connection.once('open') callback never firing

Time:03-10

I'm currently setting up a custom Node server with Next.js. The fact that I'm using Next.js shouldn't make any difference though.

In previous apps, I've always used mongoose.connection.once('open', callback) to start listening only when the database is open. This time, it's not working.

This is my connection configuration file:

import mongoose from 'mongoose';
import { MONGO_URI } from '../constants'; // looks like 'mongodb://localhost/my-db' in development

mongoose
    .connect(MONGO_URI, () => {
        try {
            console.log(`Connected to ${MONGO_URI} with Mongoose.`);
        } catch (err) {
            throw err;
        }
    })

export default mongoose.connection;

I am importing this and using it in my main.ts file like so:

import express from 'express';
import next from 'next';

import * as dotenv from 'dotenv';
import logger from 'morgan';
import compression from 'compression';
import helmet from 'helmet';

import rateLimiter from './config/rateLimiter';
import db from './config/connection'; // This is the config file

dotenv.config();

const PORT = process.env.PORT || '8000';
const dev = process.env.NODE_ENV !== 'production';

const nxt = next({ dev });
const handle = nxt.getRequestHandler();

nxt.prepare().then(() => {
    const app = express();

    app.enable('trust proxy');

    app.use(logger('dev'));
    app.use(helmet());
    app.use(rateLimiter);
    app.use(compression());
    app.use(express.urlencoded({ extended: false }));
    app.use(express.json());

    db.once('open', () => {
        app.listen(PORT, () => {
            // This log never happens
            console.log(`Listening on port ${PORT}.`);
        });
    });
});

It's extremely strange, because "Connected to mongodb://localhost/my-db with Mongoose." is in fact logged when using the code above, but the express app simply never listens; however, when I remove the app.listen out of the db.once callback function, "Listening on port 8000" does of course get logged.

I'm stumped. Why isn't the 'open' event firing? I've verified that mongo is working locally through the Mongo shell, and this same exact code was working when I had the folder which these files are in (server) separate from the Next.js app (when I was still debating which type of view layer to write).

The issue is not compatibility. I'm running Mongo 5.0.5, and Mongoose 6.2.5, which should be find according to this

Please don't link to some other question. None of these have helped:

CodePudding user response:

The comment from @Shivam Sood was correct. The db.once('open') was being called too late. Once nxt.prepare had happened, the db was already opened.

Here is the modified code:

import express from 'express';
import next from 'next';
import * as dotenv from 'dotenv';

import logger from 'morgan';
import compression from 'compression';
import helmet from 'helmet';

import rateLimiter from './config/rateLimiter';
import db from './config/connection';

dotenv.config();

const PORT = process.env.PORT || '8000';
const dev = process.env.NODE_ENV !== 'production';

const nxt = next({ dev });
const handle = nxt.getRequestHandler();

db.once('open', () => { // Listen for 'open' event before nxt.prepare, and before listening on PORT
    nxt.prepare().then(() => {
        const app = express();

        app.enable('trust proxy');

        app.use(logger('dev'));
        app.use(helmet());
        app.use(rateLimiter);
        app.use(compression());
        app.use(express.urlencoded({ extended: false }));
        app.use(express.json());

        app.get('*', (req, res) => {
            return handle(req, res);
        });

        app.listen(PORT, () => {
            console.log(`Listening on port ${PORT}.`);
        });
    });
});

CodePudding user response:

might be you need to try this way

import express from 'express';
import next from 'next';

import * as dotenv from 'dotenv';
import logger from 'morgan';
import compression from 'compression';
import helmet from 'helmet';

import rateLimiter from './config/rateLimiter';
import db from './config/connection'; // This is the config file

dotenv.config();

const PORT = process.env.PORT || '8000';
const dev = process.env.NODE_ENV !== 'production';

const nxt = next({ dev });
const handle = nxt.getRequestHandler();

nxt.prepare()
   .then(async ()=>{ 
        await db.once('open')
        const app = express();
    
        app.enable('trust proxy');
    
        app.use(logger('dev'));
        app.use(helmet());
        app.use(rateLimiter);
        app.use(compression());
        app.use(express.urlencoded({ extended: false }));
        app.use(express.json());
        
        app.listen(PORT, () => {
                // This log never happens
                console.log(`Listening on port ${PORT}.`);
        }); 
})
  • Related