Nodejs 中间件依赖注入工具 middleware-injector 如何
Nodejs 中间件依赖注入工具 middleware-injector 如何
中间件模式算是最 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’
Node.js 中间件依赖注入工具 middleware-injector 如何使用
中间件模式是 Node.js 构建 Web 应用程序的一种常见方法。然而,在使用 Express 等框架时,我发现中间件之间缺乏一种有效的依赖管理机制。为了解决这个问题,我编写了一个简单的依赖注入工具 middleware-injector
,总共只有 12 行代码。
源码
const _ = require('lodash');
const async = require('async');
module.exports = (req, res, next) => {
req.inject = (dependency, callback) => {
if (req.injected) {
dependency = _.reject(dependency, (item) => {
return req.injected.includes(item);
});
}
async.eachSeries(dependency, (item, callback) => {
if (!req.injected) {
req.injected = [];
}
req.injected.push(item);
item(req, res, callback);
}, callback);
};
next();
};
该工具已经发布到了 npm 上:middleware-injector
示例应用场景
假设我们有一个应用需要解析 token、获取账户信息,并进行错误处理。我们可以使用 middleware-injector
来管理这些中间件之间的依赖关系。
// 解析 token
const parseToken = (req, res, next) => {
req.token = req.cookies.token;
next();
};
// 获取账户信息
const accountInfo = (req, res, next) => {
req.inject([parseToken], () => {
mAccount.authenticate(req.token, (account) => {
req.account = account;
next();
});
});
};
// 错误处理
const errorHandling = (req, res, next) => {
res.error = (name, param) => {
param = _.extend(param, { error: name });
res.status(400).json(param);
};
next();
};
// 请求认证
const 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 install middleware-injector
-
引入:
const middlewareInjector = require('middleware-injector');
-
使用: 在你的 Express 应用中,将
middlewareInjector
作为中间件使用。app.use(middlewareInjector); // 使用中间件 app.use(parseToken); app.use(accountInfo); app.use(errorHandling); app.use(requestAuthenticate);
通过这种方式,你可以轻松地管理中间件之间的依赖关系,确保它们按顺序执行,并且每个中间件都能访问到所需的依赖。
中间件要安排好流程顺序就行,过多的依赖会造成维护困难,这么注入不还是链式执行。
你这个模块会不会遇到跟 npm 一样的重复依赖问题?
比如 a 和 b 都依赖 c,那么我在 a 和 b 的声明中都写了 c,这样 c 会不会被执行两次?
不会,重复的依赖只会执行一次,这也是这个工具的意义。
我是打算在应用层重度使用中间件模式的,所以不可避免地会遇到依赖管理的问题,这个工具会保证对于每个请求只会执行需要用到的中间件,并且每个中间件只执行一次。
cool …
怎么着都不如直接在app.js里先后顺序的定义来的一目了然。。。你真的需要那么多中间件么?
先后顺序其实就行了,不过这个di的想法有点意思
di 还是使用强大的 bearcat 哈
如果是这样,那么你应该要有更好的设计,而不是依赖于工具去解决。
你的 book 是不是就几个 url 用到?
这个 middleware-injector
工具允许你在 Express 中间件之间定义依赖关系,并按顺序执行这些中间件。下面是一个简化的版本,展示了如何使用这个工具来管理中间件的依赖。
首先,确保你已经安装了这个库:
npm install middleware-injector
接下来,我们来看看如何使用这个库。以下是一个简单的例子,展示了如何定义和注入中间件依赖:
示例代码
假设我们有以下几个中间件:
parseToken
: 解析并设置请求中的 token。accountInfo
: 验证账户信息。errorHandling
: 处理错误。
const express = require('express');
const injector = require('middleware-injector');
const app = express();
// 定义中间件
const parseToken = (req, res, next) => {
req.token = req.cookies.token;
next();
};
const accountInfo = (req, res, next) => {
req.inject([parseToken], () => {
// 假设 mAccount 是一个验证 token 的对象
mAccount.authenticate(req.token, (account) => {
req.account = account;
next();
});
});
};
const errorHandling = (req, res, next) => {
res.error = (name, param) => {
param = { ...param, error: name };
res.status(400).json(param);
};
next();
};
const 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', {});
}
}
});
};
// 使用中间件
app.use(injector());
app.use(parseToken);
app.use(accountInfo);
app.use(errorHandling);
app.use(requestAuthenticate);
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
解释
- 定义中间件: 我们定义了几个中间件函数,每个中间件都处理特定的任务。
- 注入依赖: 在
accountInfo
和requestAuthenticate
中,我们使用req.inject
方法来注入依赖。例如,在accountInfo
中,我们先解析 token,然后再验证账户信息。 - 使用中间件: 最后,我们将中间件添加到 Express 应用中,并使用
injector()
来管理依赖关系。
通过这种方式,我们可以更方便地管理和组织中间件之间的依赖关系,使得代码更加清晰和易于维护。