次のような単純なコードブロックがあるとします。
app.get('/', function(req, res){
res.send('Hello World');
});
この関数にreq
はres
、それぞれリクエスト オブジェクトとレスポンス オブジェクトを表す と の 2 つのパラメータがあります。
一方、 と呼ばれる 3 番目のパラメータを持つ関数もありますnext
。たとえば、次のコードを見てみましょう。
app.get('/users/:id?', function(req, res, next){ // Why do we need next?
var id = req.params.id;
if (id) {
// do something
} else {
next(); // What is this doing?
}
});
の目的next()
や、それが使用される理由が理解できません。この例では、 id が存在しない場合は、next
実際に何が行われているのでしょうか?
ベストアンサー1
次に一致するルートに制御を渡します。たとえば、上記の例では、 がid
指定された場合、データベースでユーザーを検索し、 に割り当てることができますreq.user
。
以下に、次のようなルートがあります。
app.get('/users', function(req, res) {
// check for and maybe do something with req.user
});
/users/123 は最初に例のルートと一致するため、最初に user をチェックして見つけ、123
その/users
結果を使用して何かを行うことができます。
ルートミドルウェアUsers
ただし、私の意見では、特定の URI スキームやルート順序に依存しないため、より柔軟で強力なツールです。 async を含むモデルを想定して、次のように例をモデル化したいと思いますfindOne()
。
function loadUser(req, res, next) {
if (req.params.userId) {
Users.findOne({ id: req.params.userId }, function(err, user) {
if (err) {
next(new Error("Couldn't find user: " + err));
return;
}
req.user = user;
next();
});
} else {
next();
}
}
// ...
app.get('/user/:userId', loadUser, function(req, res) {
// do something with req.user
});
app.get('/users/:userId?', loadUser, function(req, res) {
// if req.user was set, it's because userId was specified (and we found the user).
});
// Pretend there's a "loadItem()" which operates similarly, but with itemId.
app.get('/item/:itemId/addTo/:userId', loadItem, loadUser, function(req, res) {
req.user.items.append(req.item.name);
});
このようにフローを制御できるのは非常に便利です。管理者フラグを持つユーザーのみが特定のページを利用できるようにしたい場合があります。
/**
* Only allows the page to be accessed if the user is an admin.
* Requires use of `loadUser` middleware.
*/
function requireAdmin(req, res, next) {
if (!req.user || !req.user.admin) {
next(new Error("Permission denied."));
return;
}
next();
}
app.get('/top/secret', loadUser, requireAdmin, function(req, res) {
res.send('blahblahblah');
});
これがあなたにインスピレーションを与えたことを願っています!