中间件模式算是最 Node 风格的 Web 应用构建方式,但是我在使用 express 的中间件的过程中,发现似乎缺少管理中间件之间的依赖的功能,找了一些库,但是感觉这个简单的问题被描述得复杂化了,于是我自己写了一个简单的依赖注入工具,总计才 12 行。
源码贴在这里:
_ = require 'underscore'
async = require 'async'
module.exports = (req, res, next) ->
req.inject = (dependency, callback) ->
if req.injected
dependency = _.reject dependency, (item) ->
return item in req.injected
async.eachSeries dependency, (item, callback) ->
req.injected = [] unless req.injected
req.injected.push item
item req, res, callback
, callback
next()
也发在了 npm 上面: https://www.npmjs.org/package/middleware-injector 当然,这是花了半个小时搞出来的,肯定不是最好的解决方案,欢迎提供更好的解决方案。
下面是一个典型的应用场景:
parseToken = (req, res, next) ->
req.token = req.cookies.token
next()
accountInfo = (req, res, next) ->
req.inject [parseToken], ->
mAccount.authenticate req.token, (account) ->
req.account = account
next()
errorHandling = (req, res, next) ->
res.error = (name, param) ->
param = _.extend param, error: name
res.json 400, param
next()
requestAuthenticate = (req, res, next) ->
req.inject [accountInfo, errorHandling], ->
if req.account
next()
else
if req.method == 'GET'
res.redirect '/account/login/'
else
res.error 'auth_failed'
中间件要安排好流程顺序就行,过多的依赖会造成维护困难,这么注入不还是链式执行。
你这个模块会不会遇到跟 npm 一样的重复依赖问题?
比如 a 和 b 都依赖 c,那么我在 a 和 b 的声明中都写了 c,这样 c 会不会被执行两次?
不会,重复的依赖只会执行一次,这也是这个工具的意义。
我是打算在应用层重度使用中间件模式的,所以不可避免地会遇到依赖管理的问题,这个工具会保证对于每个请求只会执行需要用到的中间件,并且每个中间件只执行一次。
cool …
怎么着都不如直接在app.js里先后顺序的定义来的一目了然。。。你真的需要那么多中间件么?
先后顺序其实就行了,不过这个di的想法有点意思
di 还是使用强大的 bearcat 哈
@rekey 我是打算在应用层重度使用中间件的,比如我有几个和 book 有关的 API, 我需要根据客户端提供 book_id, 去数据库查到相应的记录再操作,这个过程我会用中间件来完成。但是并非所有请求都跟 book 有关,如此一来,中间件之间的依赖关系就很复杂了。
如果是这样,那么你应该要有更好的设计,而不是依赖于工具去解决。
你的 book 是不是就几个 url 用到?