この記事では主に、nodejs の Express の次の関数についての理解を紹介します。興味のある方は参考にしてください。
最近、同社はフロントエンドとバックエンドを分離するためにノードを使用しており、Web フレームワークを使用しています。は Express なので、Express のフレームワークについてはかなり理解できました。少し前に Express routing についての記事を書きましたが、その記事では Express の次の非常に重要な内容が抜け落ちているようなので、今日はこれを書きます。特急についてはまた別途お話します。
nextについて、主に3つのポイントから解説していきます
nextの役割は何ですか?
次はいつ使えばいいですか?
next の内部実装メカニズムは何ですか?
Next の役割
Express ミドルウェア関数を定義するとき、3 番目のパラメーターを next として定義します。next 関数は主に、次のミドルウェア If に制御を渡す役割を果たします。現在のミドルウェアがリクエストを終了せず、next が呼び出されない場合、リクエストは一時停止され、後で定義されたミドルウェアは実行される機会がありません。
Next を使用する場合
上記の説明から、next 関数は主に、登録されているすべてのミドルウェアが 1 つずつ確実に実行されるようにするために使用されることがすでにわかっています。その後、すべてのミドルウェアで 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: {} }); });
Send request"/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 のヘッダーに追加しようとするため、上記の例外がスローされます。
これを読んだ後、res.send の次の関数を呼び出さなければ、後で定義された 404 ミドルウェアは実行されないのでしょうか?ここで、res.send の後の次の関数呼び出しを削除して、リクエスト "/xxx" を送信すると、404 ミドルウェアが実行されることがわかります (ㄒoㄒ)、これは前に述べたことと矛盾しませんか、カスタマイズミドルウェアは next を呼び出さないのに、後で定義されたミドルウェアが実行されるのはなぜですか?ソースコードを見るしかないようです~~~
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); } }
上記は、問題を説明しやすくするために、ExpressのNextのソースコードです。コードが削除されました。上記のソース コードから、次の関数内に while ループがあることがわかります。各ループはスタックからレイヤーを取り出し、このレイヤーにはルーティングとミドルウェアの情報が含まれており、そのレイヤーは要求されたものと一致するために使用されます。パスの一致に成功すると、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); } }
この次は、上記のものよりもはるかに単純です。複数のミドルウェアの制御権を転送します。そして、パラメータ「route」を受け取ります。 next("route") が呼び出されると、現在のルートの他のミドルウェアをスキップし、制御を次のルートに直接渡します。
最後に、 next(err) がどのように制御をエラー処理ミドルウェアに移すかについて説明する必要があります。前のコードから、 next(err) が呼び出されるときに、express が内部でレイヤーを呼び出すことがわかります。 .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 は、fn のパラメータの数が 4 に等しくない場合に判定するミドルウェア関数です。ミドルウェアの処理エラーではないとみなされるため、next(err)の呼び出しを続けて、次のミドルウェア関数に入り、あるミドルウェアのパラメータ数まで判定を続けます。関数が 4 の場合、エラー処理ミドルウェアが見つかったとみなされ、このミドルウェア関数が実行されます。
以上がNodejsのexpressでのnext関数の使い方を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。