Home > Blockchain >  How to segment model from controller in a node api?
How to segment model from controller in a node api?

Time:06-11

I'm trying to keep my node/express api clean, but am unable to keep code effectively separate.

Most tutorials cram the data operation response into index.js like so:

app.post('/user', (req res) => {
   db.query("SELECT UserID, UserName FROM User", function (err, result, fields) {
      if (err) throw err;
      res.json(response);
   });
});

This is fine for simple tutorials, but once things get complex, I get a huge index.js file.

I'd prefer to separate User into its own class and call on it to perform data operations. However querying the database requires a promise - and I don't know how to get the data back out to the original calling function. This leaves me passing the response function in, forcing the User class to behave as both model and a little controller in MVC.

app.post('/user', (req res) => {
   var user = new User(db);
   user.getUserList(res);
   // I wish I could get the userlist back and respond here...
   });
});

(User.js)

getUserList(res) {
   db.query("SELECT UserID, UserName FROM User", function (err, result, fields) {
      if (err) throw err;
      //...but since I don't know how to get data back out of this method, I'll respond here.
      res.json(response);
   });
}

Is this just how it is in node.js? Is there a design pattern to keep these separate in node?

CodePudding user response:

What you could do is split your controllers, models and routes declarations into separate folders.

- /models
 -- user.model.js
- /controllers
 -- user.controller.js
- /routes
 -- user.route.js

Your user.model will contain the model declaration.

The user.controller will contain the functions responsible for handling an end-point operation:

const getUserList = (req, res) => {
   db.query("SELECT UserID, UserName FROM User", function (err, result, fields) {
      if (err) throw err;
      res.json(response);
   });
}

module.exports = { getUserList }

The user.route will contain the code responsible for setting up your route declarations with Express Router:

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

const { getUserList } = require('../controllers/user.controller')

router.get('/', getUserList)

module.exports = router;

Finally, in your app.js, you will just need to setup your routes with:

app.use('/user', require('./routes/user.route'))

CodePudding user response:

I see two problems here, one that your index.js file keeps growing; you should be splitting your code. There's a great tutorial on this here. secondly, you should use async/await to return results from DB. Here's how you can achieve it.

User.js

async function getUserList() {
    return db.query("SELECT UserID, UserName FROM User", function (err, result, fields) {
        if (err) throw err;
        return result;
    });
}

Controller function

app.post('/user', async (req res) => {
    var user = new User(db);
    const userList = await user.getUserList(res); // this will wait for the function to return the response
    res.json(userList);
});
  • Related