次の機能を表現する、それは本当に何のためのものですか?


124

next()メソッドが何をするかの良い説明を見つけることを試みてきました。Expressのドキュメントでは、next('route')そのルートにジャンプしてその間のすべてのルートをスキップするために使用できると記載されていますが、next引数なしで呼び出されることもあります。next機能を説明する優れたチュートリアルなどを知っている人はいますか?

回答:


160

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(err)やnext( 'route')など、nextの他の使用法もいくつか見ました。あなたはこれらの目的を果たしていますか、いつエラーを伝播したいですか、いつ特定のルートにジャンプしたいですか?
Andreas Selenwall 2012年

8
@AndreasSelenwallのnext('route')に特異的でありapp.VERB()、経路はに複数のコールバックを有する場合に使用される「残り経路コールバック(S)バイパスが。next(err)任意「にジャンプするために使用されるエラーミドルウェア(」Eポストから)。
ジョナサンロノウスキー

5
賛成。この言葉だけのために:「冗談です、私は実際にこれを処理したくありません」私が探していたものを理解させました。似たような質問がたくさんありましたが、1つのフレーズで解決策を見つけました。
ペドロ・バロス

8
next()引数なしで呼び出すことは、システムに「これを処理したくない」ことを実際に通知するのではなく、システムに、このミドルウェアの実行後に残りのミドルウェアの処理を続行するように通知するだけです。を呼び出すのはエラー状態ではなくnext()、通常のフローの一部です。呼び出さnext()ない場合、他のルートはまったく処理されません。
d512 2017

1
私はこのウェブサイトのより多くの答えが素人向けに書かれたものであることを願っています... 'next()は引数なしで「冗談です、これを処理したくないのです」」-初心者に最適...(@ d512にはより良い説明ですが)
daCoda

129

ほとんどのフレームワークでは、要求を受け取り、応答を返します。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がないことは理にかなっています。


3
この匿名のログ機能はどこに保存しますか?
dennismonsewicz 2014

「Expressは現在のスタックを中止し、4つのパラメーターを持つすべてのミドルウェアを実行します。」expressが正確なエラーハンドラーミドルウェアを実行できる方法を知りたいと思っていました。ありがとう!
Abhishek Agarwal

75

私見、この質問に対する受け入れられた答えは本当に正確ではありません。他の人が述べたように、それは実際にはチェーン内の次のハンドラーが実行されるタイミングを制御することです。しかし、より具体的にするためにもう少しコードを提供したかったのです。このシンプルなエクスプレスアプリがあるとします。

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


Sonfarが私にとって最良の答えです。
Norayr Ghukasyan

さて説明!
チャン

7

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


2
または次のミドルウェア。
robertklep 2015年

1

これは単に、次のハンドラに制御を渡すことを意味します。

乾杯


1

上記のnext()の呼び出しに注意してください。この関数を呼び出すと、アプリ内の次のミドルウェア関数が呼び出されます。next()関数はNode.jsまたはExpress APIの一部ではありませんが、ミドルウェア関数に渡される3番目の引数です。next()関数には任意の名前を付けることができますが、慣例により、常に「next」という名前が付けられています。混乱を避けるために、常にこの規則を使用してください。


0

これまでに提供された回答で週にカバーされているように思われるnext( 'route')の使用についても質問されました:

  1. next()の使用:

つまり、次のミドルウェア機能です。

この公式の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()を呼び出す必要があります。それ以外の場合、要求はハングしたままになります。」

  1. next( 'route')の使用:

つまり、次のルート(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')
})

0

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();
})
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.