在许多框架中都有使用中间件的通用方法。
在ExpressJS中-我在这里用middleware-chain
处理请求:
app.use('/url', middleware1);
app.use('/url', middleware2);
app.use('/url', middleware3);
在Telegraf中-在这里,我使用middleware-chain
处理消息事件(作为机器人):
bot.on('text', middleware1);
bot.on('text', middleware2);
bot.on('text', middleware3);
以上示例工作正常,我想实现以推迟一些请求/事件。在这种情况下,如果我的middleware-chain
目前正忙于处理某些请求/事件-我可以将新的传入事件/请求存储在DB中,并在以后middleware-chain
空闲时进行处理。这样做的主要原因是限制了某些用户一次仅发送一个请求/事件,并在middleware-chain
忙时等待响应。
让我们假设我可以在数据库中存储/检索我需要的任何东西。但是,如果我从数据库中检索了一些请求/事件,则希望通过我的所有中间件发送/传递该请求/事件。在这种情况下,如果框架不支持此功能,则需要重新实现事件冒泡。
但是我可以为此使用Observable。
ExpressJS:
const sbj = new Subject();
app.use('/url', (...args) => {
sbj.next(args)
});
observable.subscribe({
next: middleware1
});
observable.subscribe({
next: middleware2
});
observable.subscribe({
next: middleware3
});
Telegraf:
const sbj = new Subject();
bot.on('text', (...args) => {
sbj.next(args)
});
observable.subscribe({
next: middleware1
});
observable.subscribe({
next: middleware2
});
observable.subscribe({
next: middleware3
});
但是我错过了Observable-chain
中middleware-chain
=>中的一项重要功能,我可以取消下一个中间件。例如。 middleware-chain
。
如何使用middleware1 -> next -> middleware2 -> cancel
实现相同的行为(因此一个订阅可以取消另一个订阅)?我认为应该有一个优雅的解决方案。
答案 0 :(得分:2)
RxJS有其自己的“链接”机制,称为管道运算符。 as you can see here为您提供了一系列的服务。如果您具有可重用的中间件,则可以很好地将它们实现为自己的操作员。例如,身份验证运算符可能如下所示:
function authenticator() = (obs$) => obs$.pipe(
mergeMap(([req, res]) => req.isAuthenticated() ? of([req, res]) : throwError([res, "Must be authenticated!"]))
)
然后,您可以按以下方式使用它:
const sbj = new Subject();
app.use('/url', (...args) => {
sbj.next(args)
});
sbj.pipe(
authenticator(),
// more operators
).subscribe(([req, res]) => {
// send response
}, ([res, err]) => {
// send error
})
答案 1 :(得分:0)
没有可观察的表达,请提供next('route')以便您跳过中间件链 https://expressjs.com/en/guide/using-middleware.html
var app = express()
var router = express.Router()
// predicate the router with a check and bail out when needed
router.use(function (req, res, next) {
if (!req.headers['x-auth']) return next('router')
next()
})
router.get('/', function (req, res) {
res.send('hello, user!')
})
// use the router and 401 anything falling through
app.use('/admin', router, function (req, res) {
res.sendStatus(401)
})