next()
メソッドが何をするかの良い説明を見つけることを試みてきました。Expressのドキュメントでは、next('route')
そのルートにジャンプしてその間のすべてのルートをスキップするために使用できると記載されていますが、next
引数なしで呼び出されることもあります。next
機能を説明する優れたチュートリアルなどを知っている人はいますか?
next()
メソッドが何をするかの良い説明を見つけることを試みてきました。Expressのドキュメントでは、next('route')
そのルートにジャンプしてその間のすべてのルートをスキップするために使用できると記載されていますが、next
引数なしで呼び出されることもあります。next
機能を説明する優れたチュートリアルなどを知っている人はいますか?
回答:
next()
引数なしで「冗談です、私は実際にこれを処理したくない」と言います。それは戻って、マッチする次のルートを見つけようとします。
これは、URLスラッグやその他の多くの機能を備えたある種のページマネージャが必要な場合などに便利ですが、例を示します。
app.get('/:pageslug', function(req, res, next){
var page = db.findPage(req.params.pageslug);
if (page) {
res.send(page.body);
} else {
next();
}
});
app.get('/other_routes', function() {
//...
});
その構成されたコードは、特定のIDスラッグを持つページのデータベースをチェックする必要があります。見つかった場合はレンダリングしてください!見つからない場合は、このルートハンドラーを無視して、他のルートハンドラーを確認します。
したがってnext()
、引数を指定しないと、ルートを処理しなかったふりをして、代わりに別のルートがピックアップできるようになります。
またはのヒットカウンターapp.all('*')
。これにより、いくつかの共有セットアップコードを実行してから、他のルートに移動して、より具体的な何かを行うことができます。
app.all('*', function(req, res, next){
myHitCounter.count += 1;
next();
});
app.get('/other_routes', function() {
//...
});
next('route')
に特異的でありapp.VERB()
、経路はに複数のコールバックを有する場合に使用される「残り経路コールバック(S)バイパスが。」next(err)
任意「にジャンプするために使用されるエラーミドルウェア(」E
ポストから)。
next()
引数なしで呼び出すことは、システムに「これを処理したくない」ことを実際に通知するのではなく、システムに、このミドルウェアの実行後に残りのミドルウェアの処理を続行するように通知するだけです。を呼び出すのはエラー状態ではなくnext()
、通常のフローの一部です。呼び出さnext()
ない場合、他のルートはまったく処理されません。
ほとんどのフレームワークでは、要求を受け取り、応答を返します。Node.jsの非同期の性質により、重要でないことを行うと、ネストされたコールバックで問題が発生します。これが発生しないようにするために、Connect.js(v4.0より前では、Express.jsはconnect.jsの上にあるレイヤーでした)には、ミドルウェアと呼ばれるものがあります。これは、2、3、または4つのパラメーターを持つ関数です。
function (<err>, req, res, next) {}
Express.jsアプリは、これらの関数のスタックです。
ルーターは特別で、特定のURLに対して1つ以上のミドルウェアを実行できるミドルウェアです。つまり、スタック内のスタックです。
では、次に何をするのでしょうか?シンプルで、次のミドルウェアを実行するようアプリに指示します。しかし、次に何かを渡すとどうなりますか?Expressは現在のスタックを中止し、4つのパラメーターを持つすべてのミドルウェアを実行します。
function (err, req, res, next) {}
このミドルウェアは、エラーを処理するために使用されます。私は次のことをしたいです:
next({ type: 'database', error: 'datacenter blew up' });
このエラーでは、おそらくユーザーに問題が発生したことを伝え、実際のエラーを記録します。
function (err, req, res, next) {
if (err.type === 'database') {
res.send('Something went wrong user');
console.log(err.error);
}
};
Express.jsアプリケーションをスタックとして描くと、多くの奇妙さを自分で修正できるでしょう。たとえば、ルーターの後にCookieミドルウェアを追加する場合、ルートにCookieがないことは理にかなっています。
私見、この質問に対する受け入れられた答えは本当に正確ではありません。他の人が述べたように、それは実際にはチェーン内の次のハンドラーが実行されるタイミングを制御することです。しかし、より具体的にするためにもう少しコードを提供したかったのです。このシンプルなエクスプレスアプリがあるとします。
var express = require('express');
var app = express();
app.get('/user/:id', function (req, res, next) {
console.log('before request handler');
next();
});
app.get('/user/:id', function (req, res, next) {
console.log('handling request');
res.sendStatus(200);
next();
});
app.get('/user/:id', function (req, res, next) {
console.log('after request handler');
next();
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
もし、するなら
curl http://localhost:3000/user/123
これがコンソールに出力されます。
before request handler
handling request
after request handler
次のnext()
ように、中間のハンドラーでへの呼び出しをコメントアウトしたとします。
app.get('/user/:id', function (req, res, next) {
console.log('handling request');
res.sendStatus(200);
//next();
});
これはコンソールに表示されます:
before request handler
handling request
最後のハンドラ(を出力するハンドラafter request handler
)は実行されないことに注意してください。これは、次のハンドラーを実行するようにexpressに指示しなくなったためです。
したがって、「メイン」ハンドラー(200を返すハンドラー)が成功したかどうかは問題ではなく、残りのミドルウェアを実行したい場合は、を呼び出す必要がありますnext()
。
これはいつ役に立ちますか?リクエストが成功したかどうかに関係なく、いくつかのデータベースに入ってきたすべてのリクエストをログに記録したいとします。
app.get('/user/:id', function (req, res, next) {
try {
// ...
}
catch (ex) {
// ...
}
finally {
// go to the next handler regardless of what happened in this one
next();
}
});
app.get('/user/:id', function (req, res, next) {
logToDatabase(req);
next();
});
2番目のハンドラーを実行する場合はnext()
、最初のハンドラーを呼び出す必要があります。
ノードは非同期なので、最初のハンドラーのコールバックがいつ終了したかを認識できないことに注意してください。あなたはそれを電話で伝える必要がありますnext()
。
これまでに提供された回答で週にカバーされているように思われるnext( 'route')の使用についても質問されました:
つまり、次のミドルウェア機能です。
この公式のExpress JSドキュメントからの抜粋-「ライティングミドルウェア」ページ:
「ミドルウェア関数myLoggerは単にメッセージを出力してから、next()関数を呼び出すことにより、リクエストをスタック内の次のミドルウェア関数に渡します。」
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
Express JSドキュメンテーションのこのページには、「現在のミドルウェア関数が要求/応答サイクルを終了しない場合は、次のミドルウェア関数に制御を渡すためにnext()を呼び出す必要があります。それ以外の場合、要求はハングしたままになります。」
つまり、次のルート(next()の場合の次のミドルウェア関数との比較)
このExpress JSドキュメントからの抜粋-「ミドルウェアの使用」ページ:
「ルーターミドルウェアスタックから残りのミドルウェア機能をスキップするには、next( 'route')を呼び出して制御を次のルートに渡します。注:next( 'route')は、 app.METHOD()またはrouter.METHOD()関数。
この例は、/ user /:idパスへのGETリクエストを処理するミドルウェアサブスタックを示しています。
app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// render a regular page
res.render('regular')
})
// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
res.render('special')
})
next()はreqを使用したミドルウェア関数へのコールバック引数であり、resは次のコードのnextへのhttpリクエストおよび応答引数です。
app.get( '/'、(req、res、next)=> {next()});
そのため、next()は渡されたミドルウェア関数を呼び出します。現在のミドルウェア関数が要求/応答サイクルを終了しない場合は、next()を呼び出す必要があります。それ以外の場合、要求はハングしたままになり、タイムアウトになります。
複数のミドルウェア関数がapp.useまたはapp.METHODに渡される場合、各ミドルウェア関数内でnext() fnを呼び出す必要があります。そうでない場合、次のミドルウェア関数は呼び出されません(複数のミドルウェア関数が渡される場合)。残りのミドルウェア関数の呼び出しをスキップするには、ミドルウェア関数内でnext( 'route')を呼び出します。その後、他のミドルウェア関数は呼び出されません。次のコードでは、fn1内でnext()が呼び出されるため、fn1が呼び出され、fn2も呼び出されます。ただし、fn2内でnext( 'route')が呼び出されるため、fn3は呼び出されません。
app.get('/fetch', function fn1(req, res, next) {
console.log("First middleware function called");
next();
},
function fn2(req, res, next) {
console.log("Second middleware function called");
next("route");
},
function fn3(req, res, next) {
console.log("Third middleware function will not be called");
next();
})