[express]另类的控制器写法
发布于 9 年前 作者 zstxt1989 5337 次浏览 最后一次编辑是 8 年前 来自 分享

这两天开始认真学习express,一下子从php转到express还是很不习惯的。

控制器这块,一般定义一个路由中间件是这样的

var Home = require(__rootdir + '/controllers/home');
router.get('/', Home.getIndex);

home.js

module.exports.getIndex = function(req,res) {
	res.send('hello world!');	  
}

那么多个控制器如何共享一些方法呢?在基于类的面向对象写法中一般是创建一个控制器父类,一些通用的辅助方法都放在服控制器中,其他控制器继承它就ok了。

js的话通过原型继承也能实现,于是做了这样的改写。

1.创建"父类" controller.js

var controller = function(){}
module.exports = controller;

2.改造home.js

var controller = require('./controller');
module.exports.getIndex = function(req,res) {
	res.send('hello world!');	  
}
module.exports.getIndex.prototype = controller.prototype;

看上去,我只要在controller的prototype中添加一些方法就可以共享给home了,然而随之而来又有一个问题,假如这些方法需要访问 req,res对象咋办?我只知道只有中间件才能直接访问到这几个对象。。那么必须想办法在中间件(home.getIndex)中把这几个对象反过来共享给其他所有方法…有点晕了。 总之,办法还是有的,继续改造咯。

  1. controller.js

    var controller = function(req,res,next){
    	this.req = req;
    	this.res = res;
    	this.next = next;
     }
     module.exports = controller;
    

2.改造home.js

var controller = require('./controller');
module.exports.getIndex = function() {
	var handle = function(req,res,next){
		var p = new controller(req,res,next);
		res.send('hello world!');
	}
	return handle;
}

说实话,写到这里我也没兴趣去验证它能否运行了,太恶心了。

最后,我听别人说es6可以支持class了,赶紧去了解了一下,最终成功应用到项目里,改造成这样:

  1. controller.js

    class Controller {
      constructor(req,res,next) {
    	this.req = req;
    	this.res = res;
    	this.next = next;
      }
    }		
    module.exports = Controller;
    

2.home.js

var Controller = require( './controller');

class Home extends Controller {
  getIndex() {
	this.res.send('hello world');
  }
}

module.exports = function(name){
  return function(req,res,next){
	var instance = new Home(req,res,next);
	instance[name]();
  };
};

3.路由

var Home = require(__rootdir + '/controllers/home');
router.get('/', Home('getIndex'));
9 回复

es6的继承而已

这样写反而不伦不类,

@zstxt1989 你可以去看看另外一个框架Sails.js 的控制器

为啥module.exports.getIndex 直接 exports.getIndex

通用方法在 controller 中的共享,我是通过加中间件的方式来做的。

用中间件的方式的话,劣势就是所有的 controller 都接收到了这个方法。

你这个方式通过继承可以只让特定的 controller 拥有某类方法。但是其实中间件的方式,也可以做到这一点的。。。做到之后,还是代码比你现在的继承方式清晰好懂。

@alsotang 通过中间件传递的话,是不是要把方法附着在request对象上呢?

@zstxt1989 是的啊,这样一来,还能直接操作 req 里面的一些属性,而不用外部传参了

我的通用方法都是抽象出通用函数, 然后在需要的地方调用就好了, 都写到原型链会造成所有的controller不管需要不需要, 都会收到这个方法

继承存在的意义本就不是 “重用”

回到顶部