Express에서 사용되는“다음”매개 변수는 무엇입니까?


295

다음과 같은 간단한 코드 블록이 있다고 가정하십시오.

app.get('/', function(req, res){
    res.send('Hello World');
});

이 함수는 두 개의 매개 변수, 보유 req하고 res요청을 나타내는 응답이 각각 개체.

반면에이라는 세 번째 매개 변수를 가진 다른 함수가 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실제로 무엇을 하고 있습니까?


13
다음은 단순히 다음 라우트 핸들러가 요청을 처리하도록 허용합니다. 이 경우 사용자 ID가 존재 res.send하면 요청을 완료하는 데 사용 됩니다. 존재하지 않으면 오류를 발행하고 요청을 완료하는 다른 핸들러가있을 수 있습니다.
Dominic Barnes

1
그래서 당신은 내가이 말을하는지 app.post('/login',function(req,res))app.get('/users',function(req,res)) (가) 다음 호출하여 파일을 app.js에 다음 경로 인 로그인 호출합니다 ()?
Menztrual

2
아니요. Express.js 설명서의이 부분을 참조해야합니다. expressjs.com/guide.html#passing-route 제어
Dominic Barnes

3
기본적으로 다음에 실행될 경로는 요청의 URL과 일치하는 다른 경로입니다. 이 경우 다른 경로가를 통해 등록 된 app.get("/users")경우 위의 핸들러가 다음을 호출하면 실행됩니다.
Dominic Barnes

3
다음은 기본적으로 콜백입니다.
Jonathan Ong

답변:


266

다음 일치하는 경로로 제어를 전달 합니다. 예를 들어, 예를 들어, id주어진 경우 데이터베이스에서 사용자를 찾아서에 지정할 수 req.user있습니다.

아래에는 다음과 같은 경로가 있습니다.

app.get('/users', function(req, res) {
  // check for and maybe do something with req.user
});

/ users / 123은 먼저 예제의 경로와 일치하므로 먼저 사용자를 확인하고 찾습니다 123. 그 /users결과로 무언가 를 할 수 있습니다.

루트 미들웨어 는 특정 URI 체계 또는 경로 순서에 의존하지 않기 때문에 더 유연하고 강력한 도구입니다. Users비동기가 있는 모델을 가정하면 다음과 같은 예제를 모델링하는 경향이 있습니다 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');
});

이것이 당신에게 영감을 줬기를 바랍니다!


당신은 말할 수 있습니다! 논리를 특정 순서의 경로 또는 특정 URI 구조에 연결하지 않기 때문에 라우트 미들웨어로 이런 종류의 일을하는 경향이 더 큽니다 .
Asherah

5
왜 때때로 당신은 next ()를 반환하지만 때로는 그렇지 않습니다
John

6
@John : 반환 값은 실제로 무시됩니다. next()다시 전화를 걸지 않기 위해 돌아 가려고 합니다. 방금 사용하면 동일합니다 next(new Error(…)); return;.
Asherah

1
@ level0 : 반환 값이 무시됩니다. 당신은 그것을 속기라고 생각할 수 있습니다 next(new Error(…)); return;. 우리가 값을 전달하면 next, 그것은 일방적 오류 간주됩니다 . 나는 익스프레스 코드를 너무 많이 보지 않았지만 주위를 파고 나면 필요한 것을 찾을 수 있습니다 :)
Asherah

1
@ LEVEL0 : (내가 변경 한 return next(…);next(…); return;덜 혼란 그래서.)
아세라

87

또한 next () 이해하는 데 문제가 있었지만 도움 되었습니다.

var app = require("express")();

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write("Hello");
    next(); //remove this and see what happens 
});

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write(" World !!!");
    httpResponse.end();
});

app.listen(8080);

3
매우 간결합니다! 감사! 그러나 첫 번째 .get가 아닌 두 번째 것이 아닌지 어떻게 확인 합니까?
JohnnyQ

18
그것은 아래 실행에 최고 될 것 @JohnnyQ
Tapash

59

이해하기 전에 next노드의 요청-응답주기에 대해 약간의 세부 정보는 없지만 약간의 아이디어가 필요합니다. 특정 리소스에 대한 HTTP 요청을 시작하고 사용자에게 응답을 다시 보내면 (예 : res.send ( 'Hello World');

아주 간단한 예를 봅시다.

app.get('/hello', function (req, res, next) {
  res.send('USER')
})

resp.send가주기를 종료하고 제어를 라우트 미들웨어로 다시 넘겨주기 때문에 next ()가 필요하지 않습니다.

이제 다른 예를 살펴 보겠습니다.

app.get('/hello', function (req, res, next) {
  res.send("Hello World !!!!");
});

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

여기 같은 경로에 2 개의 미들웨어 기능이 있습니다. 그러나 당신은 항상 첫 번째 응답을 얻을 것입니다. 미들웨어 스택에서 먼저 마운트되고 res.send가주기를 종료하기 때문입니다.

그러나 우리가 항상“Hello World !!!!”를 원하지 않는다면 어떨까요? 답장. 어떤 조건에서는 "Hello Planet !!!!" 응답. 위의 코드를 수정하고 어떻게되는지 보자.

app.get('/hello', function (req, res, next) {
  if(some condition){
    next();
    return;
  }
  res.send("Hello World !!!!");  
});

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

무엇이 있어요 next여기서 뭐. 그렇습니다. 거스가있을 수도 있습니다. 조건이 참이면 첫 번째 미들웨어 기능을 건너 뛰고 다음 미들웨어 기능을 호출하면 "Hello Planet !!!!"응답 을 받게됩니다 .

따라서 미들웨어 스택의 다음 함수로 제어를 전달하십시오.

첫 번째 미들웨어 함수가 응답을 보내지 않고 논리를 실행 한 다음 두 번째 미들웨어 함수에서 응답을 받으면 어떻게 될까요?

아래와 같은 것 :-

app.get('/hello', function (req, res, next) {
  // Your piece of logic
  next();
});

app.get('/hello', function (req, res, next) {
  res.send("Hello !!!!");
});

이 경우 호출 할 미들웨어 기능이 모두 필요합니다. 따라서 두 번째 미들웨어 함수에 도달하는 유일한 방법은 next ();

다음에 전화하지 않으면 어떻게됩니까? 두 번째 미들웨어 기능이 자동으로 호출되는 것을 기대하지 마십시오. 첫 번째 기능을 호출하면 요청이 중단됩니다. 두 번째 함수는 절대 호출되지 않으며 응답을받지 않습니다.


따라서 유선 레이블이있는 next()것처럼 작동 goto합니까? , 세 번째 코드에서, 당신은 전화 한 번 즉 next(), res.send("Hello World !!!!"); 실행되지 않을 것이다? @Ashe는 항상 같은 실행 트리에 코드 가있는 return;애프터 next콜을 가지고 있음을 알았습니다 ... 항상 익스프레스로 체크인 할 수 있다고 생각합니까? /는 그의 텍스트 편집기로 넘어갑니다;)
ruffin

@ruffin 네, 다음 번 고토와 비슷하다고 생각할 수 있습니다. 다음은 레이블이 필요한 goto와 달리 어디로 가야하는지 알고 있습니다. 다음은 컨트롤을 다음 미들웨어 기능으로 전달합니다. 또한 원하는 이름을 '다음'으로 지정할 수 있습니다. 여기는 레이블 일뿐입니다. 그러나 모범 사례는 'next'라는 이름을 사용하는 것입니다.
Mav55

3
좋아요, 정확하지 않은 것 같습니다. 코드 ( pastin here )를 시도했으며 next()호출 후 코드 가 호출되었습니다 . 이 경우 past the next() call콘솔에 기록 된 다음 Error: Can't set headers after they are sent.두 번째 res.send호출이 실패하지만 오류가 발생 합니다. 코드 흐름 next() 호출 후 반환 되므로 @Ashe returns(또는 다른 논리 관리)가 중요합니다.
ruffin

4
@ruffin, 그래 맞아. next()나머지 명령문의 실행을 건너 뛰려면 뒤에 return 문이 필요합니다 . 지적 해 주셔서 감사합니다.
Mav55

1
문서를 해석하는 것이 아니라 명확한 예제가있는 "미들웨어"가 무엇인지 설명해 주셔서 감사합니다. 이것은 실제로 어떤 일이 발생하는지, 왜 그리고 어떻게 발생하는지에 대해 분명하게 말하는 유일한 대답이었습니다.
mc01

11

다음은 다음 미들웨어 기능으로 제어를 전달하는 데 사용됩니다. 그렇지 않으면 요청이 중단되거나 열려 있습니다.


6
이 답변이 7 살짜리 질문에 어떻게 추가되는지 잘 모르겠습니다.
mherzig

간단히 말하지만
hmak

@ mherzig, 그것은 하나의 라이너이고 모든 것을 다룹니다
M. Gopal

5

이 함수를 호출하면 앱에서 다음 미들웨어 함수가 호출됩니다. next () 함수는 Node.js 또는 Express API의 일부가 아니지만 미들웨어 함수에 전달되는 세 번째 인수입니다. next () 함수는 무엇이든 명명 될 수 있지만, 관례 적으로 항상“next”로 명명됩니다.


2

next기능을 실행하면 서버에이 미들웨어 단계가 완료되었음을 알리고 체인에서 다음 단계를 실행할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.