2012-10-30 17 views
77

next()メソッドの詳細な説明を探しています。 Expressドキュメントでは、next('route')を使用してそのルートにジャンプし、その間のすべてのルートをスキップすることができますが、引数なしでnextが呼び出されることがあります。 nextの機能を説明する良いチュートリアルなどは、誰もが知っていますか?エクスプレス次の機能、それは本当に何ですか?

答えて

105

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() { 
    //... 
}); 
+0

偉大な答え! 次の他の用途も見てきました。次の(エラー)と次の( 'ルート')。あなたは今これらの目的を果たしていますか?エラーを伝播したいときはいつですか。いつ特定のルートにジャンプしたいですか? –

+7

@AndreasSelenwall 'next( 'route')'は['app.VERB()'](http://expressjs.com/api.html#app.VERB)に固有で、ルートに複数のコールバックがある場合に使用されます"*エラーミドルウェア(http://stackoverflow.com/a/7151775/15031)"( 'E ')にジャンプするために' 'next(err)ポストから)。 –

+2

Upvoted。ちょうどこの句のために:「ただ冗談を言って、私は実際にこれを処理したくない」と私はあなたが私が探していたものを理解できるようにしました。私は似たような質問をたくさん見て、1つのフレーズで解決策を見つけました。 –

102

ほとんどのフレームワークではリクエストを受け取り、返信したいと考えています。 Node.jsの非同期性のために、あなたは些細でないことをしている場合、ネストされたコールバックに問題があります。これを避けるため、Connect.js(v4.0以前はExpress.jsはconnect.jsの上にあるレイヤーでした)には、2つ、3つまたは4つのパラメーターを持つ関数であるミドルウェアと呼ばれるものがあります。

function (<err>, req, res, next) {} 

Express.jsアプリは、これらの機能のスタックです。

enter image description here

ルータは、それはあなたが特定のURLに対して一の以上のミドルウェアを実行することができますミドルウェアです、特別です。スタック内のスタックです。

次に何をしますか?シンプルで、次のミドルウェアを実行するようにアプリに指示します。しかし、次に何かを渡すとどうなりますか? 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がないことが意味を成します。

+7

すばらしい答え。 –

+3

この匿名ロギング機能はどこに保存しますか? – dennismonsewicz

5

パラメータなしのnext()は、フレームワーク内の次のルートハンドラを呼び出します。

+0

または次のミドルウェア。 – robertklep

18

IMHO、この質問に対する回答は本当に正確ではありません。他の人が述べているように、チェーンの次のハンドラがいつ実行されるかは本当に制御しています。しかし、もっと具体的にするためにもう少しコードを提供したかったのです。あなたは

curl http://localhost:3000/user/123 

を行う場合は、これがコンソールに出力が表示されます

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!') 
}); 

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(); 
}); 

は、コンソール上でこれを表示されます。最後のハンドラ(after request handlerを出力1)が実行されないことを

before request handler 
handling request 

お知らせ。それは、あなたがもはや次のハンドラを実行するように明言していないからです。

"メイン"ハンドラ(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()を呼び出すことでそれを伝える必要があります。

+0

これは本当に明確な説明です。ありがとう。 – swdon

関連する問題