12

次のように、このルート用の「ルート固有のミドルウェア」のチェーンがあります。

    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]route 固有のミドルウェアです/some/path

これは、次のようなサーバー全体のミドルウェアとは異なります。

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

定義されたすべてのルートに適用される場所。

今私の問題は、チェーンから抜け出したいということです。successつまり、で が false の場合mw1、呼び出されたくありませんmw2successで false の場合はmw2、ルート関数を呼び出さずにはいられません。現在、 と の両方が呼び出されているかどうかに関係なく呼び出されているように見えますがmw1、その理由はわかりません。mw2next()

どうすればこれを行うことができますか?

4

3 に答える 3

20

Express API リファレンスのセクションnext( 'route' )で述べたように、 を呼び出すことができます。application routing

複数のコールバックを指定することができ、すべてが同等に扱われ、ミドルウェアのように動作しますが、これらのコールバックがnext('route')残りのルート コールバックをバイパスするために呼び出すことができる例外が 1 つあります。

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();
}
于 2013-06-21T09:56:25.620 に答える
2

もう少しいじくり回すと、答えが得られました。

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()を行うことはありません。

于 2013-06-21T16:11:11.093 に答える
1

next()ルート処理関数で呼び出しも応答も送信しないと、エクスプレスがハングするという印象を受けました。また、私は配列を使用していないFWIW、私のように見えますserver.post('/some/path', mw1, mw2, function(req, resp) {...

ともかく。1 つの代替手段として、コードを再構築して、処理関数を 1 つだけにすることが考えられます。ハンドラーが呼び出す通常の非同期関数ではなく、mw1 と mw2 がミドルウェアである正当な理由はありますか?

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);
于 2013-06-21T14:24:57.930 に答える