Node.js에서 next ()를 사용하고 next ()를 반환하는시기


136

시나리오 : 다음은 노드 웹 앱의 코드 일부임을 고려하십시오.

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next(); //or return next();
    }
});

문제 : 난 그냥 함께 가야하는 하나 확인하고 next()return next(). 위의 샘플 코드는 모두 동일하게 작동하며 실행에 차이가 없었습니다.

질문 이 몇 가지 하나 개 넣어 빛이 때 사용할 수 next()때 사용하는 return next()몇 가지 중요한 차이점?

답변:


141

일부 사람들은 항상 return next()콜백을 트리거 한 후 실행이 중지되도록하는 것입니다.

그렇게하지 않으면 나중에 콜백을 트리거 할 위험이 있으며, 결과적으로 심각한 결과를 초래합니다. 귀하의 코드는 정상이지만 다음과 같이 다시 작성합니다.

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;

    if(!id)
        return next();

    // do something
});

그것은 들여 쓰기 수준을 저장하고 나중에 코드를 다시 읽을 때 next두 번 호출되는 방법 이 없다고 확신 합니다.


2
비슷한 일이 참겠습니까 res.redirect('/')return res.redirect('/')이러한 유형의 상황에서? 헤더를 보낸 후 설정 오류가 발생하지 않도록 항상 res 문 앞에 return을 작성하는 것이 더 낫습니다.
Adam D

185

@Laurent Perrin의 답변으로 :

그렇게하지 않으면 나중에 콜백을 트리거 할 위험이 있습니다.

다음과 같이 미들웨어를 작성하는 경우 여기에 예제를 제공합니다.

app.use((req, res, next) => {
  console.log('This is a middleware')
  next()
  console.log('This is first-half middleware')
})

app.use((req, res, next) => {
  console.log('This is second middleware')
  next()
})

app.use((req, res, next) => {
  console.log('This is third middleware')
  next()
})

콘솔의 출력은 다음과 같습니다.

This is a middleware
This is second middleware
This is third middleware
This is first-half middleware

즉, 모든 미들웨어 함수가 완료된 후 next () 아래 코드를 실행합니다.

그러나을 사용하면 return next()즉시 콜백을 건너 뛰고 콜백 return next()에서 아래 코드에 도달 할 수 없습니다.


29
express이 답변 의 초보자로서 다른 답변보다 나에게 분명했습니다. 엄지 손가락!
만다린

1
비슷한 일이 참겠습니까 res.redirect('/')return res.redirect('/')이러한 유형의 상황에서? 헤더를 보낸 후 설정 오류가 발생하지 않도록 항상 명령문 return앞에 작성하는 것이 더 낫 res습니다.
Adam D

1
next () 후에 왜 코드를 작성해야합니까? 미들웨어에서 작업을 완료 한 후 아무 작업도 수행하지 않는 것이 분명하지 않습니까? @PJCHENder
Imran Pollob

1
@ImranPollob 때때로 실수가 발생합니다. 많은 코드를 작성할 때 ifs / elses / etc. 당신은```return next ()`를 잊을 수도 있습니다
Jone Polvora

46

next()connect 미들웨어의 일부입니다 . 라우터 흐름에 대한 콜백은 당신이 당신의 기능에서 아무것도 반환 그래서 만약, 상관하지 않는다 return next()next(); return;기본적으로 동일합니다.

기능의 흐름을 멈추고 싶다면 next(err)다음과 같이 사용할 수 있습니다

app.get('/user/:id?', 
    function(req, res, next) { 
        console.log('function one');
        if ( !req.params.id ) 
            next('No ID'); // This will return error
        else   
            next(); // This will continue to function 2
    },
    function(req, res) { 
        console.log('function two'); 
    }
);

next()요청의 미들웨어를 확장하는 데 거의 사용됩니다.


1
다음과 같은 매개 변수를 보낼 수 있습니까 next('No ID')?
Amol M Kulkarni

7
next('No ID')실제로 오류를 보내고 있으므로 흐름이 중단됩니다.
drinchev

next (null, "somevalue")를 사용하십시오. async.waterfall과 같은 도구의 경우 값을 다음 함수로 전달합니다. 데이터 중심의 복잡한 일련의 상호 작용의 경우 일반적으로 함수간에 컨텍스트 개체를 전달합니다. 그렇게하면 컨텍스트에서 데이터를 통해 여러 끝점에서 공유하고 흐름을 제어 할 수있는 일반 기능을 만들 수 있습니다.
Chad Wilson

5
"그래서 next ()와 next ()를 반환; return;은 기본적으로 동일합니다." -내가 읽어야 할 것. thx @drinchev
Nick Pineda

1
나는 반대 (발사 오류가있을 때)를 관찰합니다 : next (error)는 다음 미들웨어를 트리거하지만 코드를 계속 실행합니다. return next (error)는 실행을 다음 미들웨어로 위임합니다. next (e)와 return next (e)는 동일하지 않습니다.
Nickolodeon

0

전혀 사용하지 않는 것이 가장 좋습니다! 나는 설명하고 그것이 또한 설명하는 것입니다.

이름과 규칙을 사용할 수있는 next () 함수는 next로 설정되었습니다. 예를 들어 동일한 URI 리소스에서 일반적으로 수행되는 작업 (PUT, GET, DELETE, ...)과 간접적으로 관련됩니다./ user /: id

app.get('/user/:id', function (req,res,next)...)
app.put('/user/:id', function (req,res,next)...)
app.delete('/user/:id', function (req,res,next)...)
app.post('/user/', function ()...)

이제 app.get, app.put 및 app.delete를 보면 동일한 URI (/ user / : id)를 사용하는 경우이를 차별화하는 유일한 방법은 구현입니다. 요청이 작성되면 (req) express가 req를 먼저 app.get에 넣을 때 해당 요청이 해당 컨트롤러에 대한 것이 아니기 때문에 생성 한 유효성 검증에 실패하면 req가 te 파일의 다음 경로 인 app.put으로 요청을 전달합니다. 의 위에. 아래 예에서 볼 수 있듯이.

    app.get('/user/:id', function (req,res,next){

    if(req.method === 'GET')
    //whatever you are going to do
    else
      return next() //it passes the request to app.put

    //Where would GET response 404 go, here? or in the next one. 
    // Will the GET answer be handled by a PUT? Something is wrong here.

   })
    app.put('/user/:id', function (req,res,next){

    if(req.method === 'PUT')
    //whatever you are going to do
    else
      return next()

   })

문제는 결국 req의 유효성 검사를 통해 원하는 것을하는 컨트롤러가 있기를 희망하면서 모든 컨트롤러에 req를 전달한다는 것입니다. 결국 모든 컨트롤러는 자신에게 적합하지 않은 것을받습니다.

그렇다면 다음 ()의 문제를 피하는 방법은 무엇입니까?

대답은 정말 간단합니다.

1- 자원을 식별하기위한 URI가 하나만 있어야 합니다.

URI가 이보다 길면 http : // IpServidor / colection / : resource / colection / : resource 새로운 URI 생성을 고려해야합니다.

http : // IpServidor / users / pepe / contacts / contacto1

2-이 자원에 대한 모든 조작은 http (get, post, put, delete 등) 동사의 dem 등원과 관련하여 수행되어야하므로 URI에 대한 호출에는 실제로 한 가지 호출 방법 만 있습니다.

POST http://IpServidor/users/  //create a pepe user 
GET http://IpServidor/users/pepe  //user pepe returns   
PUT http://IpServidor/users/pepe  //update the user pepe 
DELETE http://IpServidor/users/pepe  //remove the user pepe

추가 정보 [ https://docs.microsoft.com/es-es/azure/architecture/best-practices/api-design#organize-the-api-around-resources][1]

코드를 보자! next ()를 사용하지 않도록하는 구체적인 구현!

index.js 파일에서

//index.js the entry point to the application also caller app.js
const express = require('express');
const app = express();

const usersRoute = require('./src/route/usersRoute.js');

app.use('/users', usersRoute );

usersRoute.js 파일에서

    //usersRoute.js
    const express = require('express');
    const router = express.Router();

    const getUsersController = require('../Controllers/getUsersController.js');
    const deleteUsersController = require('../Controllers/deleteUsersController.js');

    router.use('/:name', function (req, res) //The path is in /users/:name
    {
    switch (req.method)
    {
    case 'DELETE':
      deleteUsersController(req, res);
      break;
    case 'PUT':
     // call to putUsersController(req, res);
     break;
    case 'GET':
     getUsersController(req, res);
     break;
    default:
     res.status(400).send('Bad request');
    } });

router.post('/',function (req,res) //The path is in /users/
{
    postUsersController(req, res);
});

module.exports = router;

이제 usersRoute.js 파일은 usersRoute라는 파일이 수행 할 것으로 예상되는 작업을 수행합니다. 즉, URI / users /의 경로를 관리합니다.

//getUsersController.js 파일

//getUsersController.js
    const findUser= require('../Aplication/findUser.js');
    const usersRepository = require('../Infraestructure/usersRepository.js');

    const getUsersController = async function (req, res)
    {

       try{
          const userName = req.params.name;
        //...
          res.status(200).send(user.propertys())

        }catch(findUserError){
           res.status(findUserError.code).send(findUserError.message)
        }
    }
   module.exports = getUsersController;

이런 식으로 다음 사용을 피하고 코드를 분리하고 성능을 향상 시키며 SOLID를 개발하며 마이크로 서비스로 마이그레이션 할 수있는 문을 열어두고 프로그래머가 쉽게 읽을 수 있습니다.


2
이것은 올바르지 않습니다. app.get은 제안한 것처럼 app.put에 전달되지 않습니다. 메소드가 GET이면 일치하는 요청 만 호출되므로 app.get 미들웨어 만 호출됩니다. 미들웨어는 요청 방법을 확인할 필요가 없습니다. 귀하의 제안은 express의 기본 기능을 무시하고 대신 자체 라우팅을 구현합니다. 또한 라우팅은 경로를 전달하지 않는 유일한 미들웨어라고 가정합니다.
Ravenex

잘못된 정보는 위의 답변을 참조하십시오.
DDiamond

-3

다음() :

이 함수를 호출하면 앱에서 다음 미들웨어 함수가 호출됩니다. next () 함수는 Node.js 또는 Express API의 일부가 아니지만 미들웨어 함수에 전달되는 세 번째 인수입니다.

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