在express / nodejs中退出特定链路的中间件

我有一个这条路线的“路线特定中间件”链,就像这样:

var express = require('express'); var server = express(); var mw1 = function(req, resp, next) { //do stuff if (success) { next(); } else { req.connection.destroy(); //without calling next() } }; var mw2 = function(req, resp, next) { //do stuff if (success) { next(); } else { req.connection.destroy(); //without calling next() } }; server.post('/some/path', [mw1, mw2], function(req, resp) { //write response }); 

[mw1, mw2]是特定于路由/some/path的中间件。

这与以下服务器级别的中间件不同:

  server.use(mw1); server.use(mw2); 

它适用于所有定义的路线。

现在我的问题是,我想退出链条。 也就是说,如果mw1 success是错误的,我不希望mw1被调用。 如果mw2 success是错误的,我并不是没有路由function被调用。 目前, mw1mw1似乎被调用是否调用next() – 我不知道为什么。

我怎么能这样做?

您可以调用next( 'route' ) ,如express API参考中所述, application routing部分 :

可能会给出多个callback,所有处理都是平等的,并且像中间件一样行为,除了这些callback可能会调用next('route')来绕过剩余的路由callback。

 var express = require('express') , app = express() ; // keep an eye on the function names app.post( '/some/path', middleware1, middleware2, function route1( req, res, next ) { // write response }); app.all( '*', function route2( req, res, next ) { // do something like handle a 404 request }); app.use(function errorHandler( err, req, res, next ) { // handle error }); function middleware1( req, res, next ) { // ... if ( !success ) { // bypasses middleware2 and route1, route2 will be called return next( 'route' ); } // calls middleware2 next(); } // intentionally similar to middleware1 to keep things clear function middleware2( req, res, next ) { if ( !success ) { // bypasses route1 and route2 // errorHandler will be called with the error return next( Error( 'middleware 2 failed' ) ); } // calls route1 next(); } 

我的印象是,如果你既没有在路由处理函数中调用next()也没有发送响应,那么expression就是挂起。 也FWIW我没有使用一个数组,我看起来像server.post('/some/path', mw1, mw2, function(req, resp) {...

无论如何。 一种替代scheme可能是重构你的代码,所以你只有一个处理函数。 mw1和mw2是否是中间件,而不是你的处理程序调用的常规asynchronous函数?

 var express = require('express'); var server = express(); var mw1 = function(req, res, callback) { // do stuff with req/res if necessary but don't send a response if (success) { callback(null); } else { callback('Error'); } }; var mw2 = function(req, res, callback) { //do other stuff but don't send a response if (success) { callback(null); } else { callback('Error'); } }; function mwBoth(req, res){ mw1(req, res, function(err){ if(err){ return res.send(500) }; mw2(req, res, function(err){ if(err){ return res.send(500) }; // neither had an error res.redirect('/some/other/path'); }); }); }; server.post('/some/path', mwBoth); 

多一点修补得出答案:

 var express = require('express'); var server = express(); var mw1 = function(req, resp, next) { //do stuff if (success) { next(); } else { resp.send(406, 'Invalid because of this'); req.connection.destroy(); //without calling next() } }; var mw2 = function(req, resp, next) { //do stuff if (success) { next(); } else { resp.send(406, 'Invalid because of that'); req.connection.destroy(); //without calling next() } }; server.post('/some/path', [mw1, mw2], function(req, resp) { //write response }); 

诀窍是发送一个响应: resp.send(406, 'Invalid because of this');

就在销毁连接之前: req.connection.destroy();

其实并没有破坏这个联系,我发现在一般情况下也是有效的。

(但在我的具体情况下是必需的,超出了这个问题的范围。)

如果响应已经被发送,那么Express不会自动为你调用next() ,因为看起来不是这样。