Home > Software design >  Express: Route is not created inside async function
Express: Route is not created inside async function

Time:10-29

This is the api.js module which creates a test route:

'use strict';

module.exports = function (app) {
  
  console.log("before route creation");
  app.get("/api/test", (req, res) => {
    res.send("it worked");
  });
  console.log("routes created");
};

In the server.js file, I am importing this module as apiRoutes. Then, I am calling it inside an async function.

const databaseConnection = async (apiRoutes, app) => {
  try {
    await mongoose.connect(`mongodb srv://replitUser:${process.env.DB_PW}@issuetracker.pbbm6.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`);
    console.log("db connection successful");

    //Routing for API 
    console.log("apiRoutes called");
    apiRoutes(app);  

  } catch (err) {
    console.log("an err occurred", err);
  }
}
databaseConnection(apiRoutes, app);
// apiRoutes(app);

The strings "before route creation" and "routes created" are logged to the console. However, the route does not seem to work, although no errors are occurring.

If I call apiRoutes outside of the async function, like here:

const databaseConnection = async (apiRoutes, app) => {
  try {
    await mongoose.connect(`mongodb srv://replitUser:${process.env.DB_PW}@issuetracker.pbbm6.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`);
    console.log("db connection successful");

    //Routing for API 
    // console.log("apiRoutes called");
    // apiRoutes(app);  

  } catch (err) {
    console.log("an err occurred", err);
  }
}
databaseConnection(apiRoutes, app);
apiRoutes(app);

...it will create the test route successfully.

I've tried to create the route directly inside of the async function and not in a new module, and it changed nothing, the route is still not created.

const databaseConnection = async (apiRoutes, app) => {
  try {
    await mongoose.connect(`mongodb srv://replitUser:${process.env.DB_PW}@issuetracker.pbbm6.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`);
    console.log("db connection successful");

    //Routing for API 
    // console.log("apiRoutes called");
    // apiRoutes(app);  
    app.get("/api/test", (req, res) => {
      res.send("it worked");
    });
  } catch (err) {
    console.log("an err occurred", err);
  }
}
databaseConnection(apiRoutes, app);

Why can't I create routes inside of an async function?

Here is a link to the project on replit - Feel free to fork

CodePudding user response:

I know it's not direct answer to Your question.

But the problem is that You cannot structure Your code correctly.

So in below You can see app structure with separate db and app module where app starts listening after db connection.

server.js

const http = require('http');

const db = require('./db');
const app = require('./app');

const server = http.createServer(app);
const PORT = process.env.PORT || 8000;

(async () => {
  await db.connect();
  console.log('connected to db');

  server.listen(PORT, () => {
    console.log(`app listening at port: ${PORT}`);
  });      
})();

db.js

const mongoose = require('mongoose');

const UserSchema = require('./schemas/User');
mongoose.model('User', UserSchema);

module.exports = {
  connect: function() {
    const dsn = `mongodb srv://replitUser:${process.env.DB_PW}@issuetracker.pbbm6.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`;
    return mongoose.connect(dsn);
  },
  model: function(name) {
    return mongoose.model(name);
  },
};

app.js

const express = require('express');
const app = express();

const routes = require('./routes');
app.use(routes);

module.exports = app;

routes/index.js

const express = require('express');
const router = express.Router();

const users = require('./users');
router.use('/api/users', users);

module.exports = router;

routes/users.js

const express = require('express');
const router = express.Router();

const db = require('../db');
const User = db.model('User');

router.get('/', async (req, res) => {
  const users = await User.find({}).lean();
  res.status(200).send({users});
});

router.get('/:id', async (req, res) => {
  const user = await User.findById(req.params.id).lean();
  if (!user) {
    return res.status(404).end();
  }
  res.status(200).send(user);
});

module.exports = router;

schemas/User.js

const mongoose = require('mongoose');
const {Schema} = mongoose;

const UserSchema = new Schema({
  username: Schema.Types.String,
  password: Schema.Types.String,
  name: Schema.Types.String,
});

module.exports = UserSchema;

CodePudding user response:

The solution is to simply use express.Router().

First, I had to create a router and mount it to the /api path:

const router = express.Router();
app.use("/api", router);

Then, I can create the route with router.get() instead of app.get().

const databaseConnection = async (router) => {
  try {
    await mongoose.connect(`mongodb srv://replitUser:${process.env.DB_PW}@issuetracker.pbbm6.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`);
    console.log("db connection successful");

    //Routing for API 
    // console.log("apiRoutes called");
    // apiRoutes(router);  
    router.get("/test", (req, res) => {
      res.send("it worked");
    });
  } catch (err) {
    console.log("an err occurred", err);
  }
}
databaseConnection(router);

I don't know why, but now the route works as expected. It also works if I create the routes in the apiRoutes module.

Here is a link to the fixed project on replit

  • Related