Reputation: 524
I'm newbie in web development and have developed a web server using node and express. I've used MVC pattern for this, with models being sequelizejs objects. But, for my controllers, thee's little to no OOP currently and I'd like to know some OO-way of writing controllers rather than using anonymous functions to serve requests:
app.get('/test',function(req,res){})
Maybe I can create objects for each route by using the URL and model as properties and methods that are HTTP verbs:
//Use test.model for interacting with model
app.get(test.URL,test.get);
app.post(test.URL,test.post);
app.put(test.URL,test.put);
app.patch(test.URL,test.patch);
app.delete(test.URL,test.delete);
But, it looks like overkill because most/all controller objects made this way will end up being singletons with no inheritance, polymorphism and reuse.
Question: Is there a better OO way to write controllers ?
Upvotes: 4
Views: 7472
Reputation: 54792
I have written a simple example in TypeScript which shows how to write a controller for an express application, having Object-oriented programming in mind. It can be easily applied to ES6:
Server.ts
import * as express from 'express';
import {CategoryController} from 'src/view/CategoryController';
export default class Server {
public app: express.Application;
constructor() {
this.app = express();
this.app.get('/', (request, response) => response.send('Root page without OOP.'));
// Using a controller to serve a view
this.app.use('/categories', CategoryController);
}
}
CategoryController.ts
import {Router, Request, Response} from 'express';
const router: Router = Router();
router.get('/', (request: Request, response: Response): Response => {
const payload: { [index: string]: string[] } = {categories: ['CSS', 'HTML', 'JavaScript', 'TypeScript']};
return response.json(payload);
});
export const CategoryController: Router = router;
Upvotes: 1
Reputation: 15018
One way to organize express in an OOP manner is to use an existing framework that provides the scaffolding for this. sails.js is the most popular MVC framework for node nowadays, and uses express.js for routing.
Upvotes: 0
Reputation: 4748
You could have a controller class, where its constructor accepts an express object, setting up routes for you. So this is an example base Controller
class:
/**
* @param connect can either be Sencha Labs' `connect` module, or
*/
function Controller(express) {
var self = this;
var name = '/' + this._name;
express.post(name, function (req, res, next) {
self._create(req, res, next);
});
express.get(name, function (req, res, next) {
self._read(req, res, next);
});
express.put(name + '/:id', function (req, res, next) {
self._update(req, res, next);
});
express.delete(name + '/:id', function (req, res, next) {
self._delete(req, res, next);
});
}
// Since there aren't any protected variables in JavaScript, use
// underscores to tell other programmers that `name` is protected. `name`
// (or, more technically, `_name`) is still accessible, but at least, if a
// team is disciplined enough, they'd know better than to access variables
// with underscores in them.
Controller.prototype._name = '';
Controller.prototype._create = function (req, res, next) {
};
Controller.prototype._read = function (req, res, next) {
};
Controller.protoype._update = function (req, res, next) {
};
Controller.prototype._delete = function (req, res, next) {
};
And then, you can create a Users
controller by extending from the Controller
"class":
function UsersController(express) {
Controller.call(this, express);
}
// This is not the most perfect way to implement inheritance in JavaScript,
// this is one of the many ways.
UsersController.prototype = Controller.prototype;
UsersController.prototype._name = 'users'
// An example override of the base `Controller#create` method.
UsersController.prototype._create = function (req, res, next) {
db.save(req.body, function (err) {
if (err) res.send(500, err.message);
res.redirect('/');
});
};
UsersController.prototype._read = function (req, res, next) {
db.read(function (err, users) {
if (err) res.send(500, err.message);
res.send(users);
});
};
Once you have all the appropriate controllers declared and defined, you can start implementing them onto your express app.
// Initialize a new instance of your controller.
var usersController = new UsersController(app);
P.S.: For the express calls in the constructor, there is another way to add your create
, read
, update
, delete
routes (and any other routes). I just didn't want to confuse you at first.
function Controller(express) {
var name = '/' + this._name;
express.post(name, this._create.bind(this));
express.get(name, this._read.bind(this));
express.put([name , ':id'].join('/'), this._update.bind(this));
express.delete([name, ':id'].join('/'), this._delete.bind(this));
};
Upvotes: 15
Reputation: 99225
Not really the answer, but I created a node module to handle automatically setting up express routes. Dynamic-Routes
//app.js
require('dynamic-routes')(app, __dirname + '/routes/');
then
//routes/index.js
module.exports = {
priority: 1000, //this is the `/` handler, should it should be the last route.
path: '/',
//this function gets passed the express object one time for any extra setup
init: function(app) {
app.head(function(req, res) {});
},
GET: function(req, res) {
res.end('GET ');
},
POST: function(req, res) {
res.json(req.data);
}
};
Upvotes: 0