今回は、express で next を動作させるための 注意事項 についてお届けします。 ここでは、express で next を動作させるための
注意事項 について説明します。nodejsのexpressのnextについてよく知らない人が多いと思いますが、今日の記事ではnextが何をするのか、どのような状況で使われるのかを詳しく紹介します。興味があれば一緒に調べてみましょう。
最近、同社はフロントエンドとバックエンドを分離するためにノードを使用しています。使用されているWebフレームワークはExpressであるため、Expressルーティングについての記事を以前に書きましたが、あるようです。その記事には重要なことが 1 つあります。内容は特急の次です。今日は特急の次について個別に説明します。
関数を定義するとき、この next は主に、現在のミドルウェアがリクエストを終了しない場合に制御を渡す役割を果たします。 next が呼び出されない場合、リクエストは一時停止され、後で定義されたミドルウェアは実行される機会がありません。
次へを使用する場合
上記の説明から、next 関数は主に、登録されているすべてのミドルウェアが順番に実行されるようにするために使用されることがわかりました。その後、すべてのミドルウェアで next 関数を呼び出す必要がありますが、ミドルウェアを定義する場合は特殊なケースがあります。このリクエストを終了するので、次の関数を再度呼び出すべきではありません。そうしないと問題が発生する可能性があります。コード
app.get('/a', function(req, res, next) { res.send('sucess'); next(); }); // catch 404 and forward to error handler app.use(function(req, res, next) { console.log(404); var err = new Error('Not Found'); err.status = 404; next(err); }); app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); });
を見てみましょう。 リクエスト「/a」を送信すると、コンソールの印刷ログは次のようになります:
404 GET /a 500 6.837 ms - - Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:345:11)
コードが例外をスローするのはなぜですか? これは、リクエストが終了したにもかかわらず、後続の 404 ミドルウェアが引き続き実行され、後続のミドルウェアが属性値の追加を試みるためです。ヘッダーに追加するため、上記の例外がスローされます。
これを読んだ後、res.send の次の関数を呼び出さなければ、後で定義された 404 ミドルウェアは実行されないのではないかという疑問が生じるかもしれません。ここで、res.send の後の次の関数呼び出しを削除して、リクエスト "/xxx" を送信すると、404 ミドルウェアが実行されることがわかります (ㄒoㄒ)、これは前に述べたことと矛盾しませんか、カスタマイズミドルウェアは next を呼び出さないのに、後で定義されたミドルウェアが実行されるのはなぜですか?ソースコードについてのみ助けを求めることができるようです~~~
次は内部の仕組みfunction next(err) {
... //此处源码省略
// find next matching layer
var layer;
var match;
var route;
while (match !== true && idx < stack.length) {
layer = stack[idx++];
match = matchLayer(layer, path);
route = layer.route;
if (typeof match !== 'boolean') {
// hold on to layerError
layerError = layerError || match;
}
if (match !== true) {
continue;
}
... //此处源码省略
}
... //此处源码省略
// this should be done for the layer
if (err) {
layer.handle_error(err, req, res, next);
} else {
layer.handle_request(req, res, next);
}
}
があることがわかります。各ループはスタックからレイヤーを取り出し、そのレイヤーと要求されたパスが含まれています。一致する場合、layer.handle_request が実行され、ミドルウェア関数が呼び出されます。ただし、一致に失敗すると、次の層 (ミドルウェア) がループされます。
ここで、上で挙げた問題、つまりカスタム ミドルウェアで次の関数が呼び出されないのに、要求した "/xxx" が登録した "/a" と一致しないため、後続の 404 ミドルウェアが引き続き実行される理由を説明できます。ミドルウェアをルーティングするため、while ループは実行を継続します。一致する 404 ミドルウェアが成功すると、404 ミドルウェアが実行されます。
注: app.use で登録されたミドルウェアの場合、パス パラメーターが空の場合、デフォルトは「/」になり、パスが「/」のミドルウェアはデフォルトですべてのリクエストに一致します。 実際、ルーティング
ミドルウェアを定義するとき、関数の次の 3 番目のパラメーターは、非ルーティング ミドルウェアを定義するときの関数の 3 番目のパラメーターと同じではありません。上を見た 非ルーティングミドルウェアの次の機能、ルーティングミドルウェアの次の機能はこんな感じです🎜function next(err) { if (err && err === 'route') { return done(); } var layer = stack[idx++]; if (!layer) { return done(err); } if (layer.method && layer.method !== method) { return next(err); } if (err) { layer.handle_error(err, req, res, next); } else { layer.handle_request(req, res, next); } }
这个next比上边的那个next要简单很多,它负责同一个路由的多个中间件的控制权的传递,并且它会接收一个参数"route",如果调用next(“route”),则会跳过当前路由的其它中间件,直接将控制权交给下一个路由。
最后有必要再说一说next(err),next(err)是如何将控制权传递到错误处理中间件的,从前边的代码我们知道,当调用next(err)是,express内部会调用layer.handle_error,那我们来看看它的源码
Layer.prototype.handle_error = function handle_error(error, req, res, next) { var fn = this.handle; if (fn.length !== 4) { // not a standard error handler return next(error); } try { fn(error, req, res, next); } catch (err) { next(err); } };
代码中的fn就是中间件函数,express会对fn的参数个数进行判断,如果参数个数不等于4则认为不是错误处理中间件,则继续调用next(err),这样就会进入到下一个中间件函数,继续进行参数个数判断,如此方式一直到某个中间件函数的参数个数是4,就认为找到了错误处理中间件,然后执行此中间件函数。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上が次にnodejsはexpressで動作しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。