Expresse a próxima função, para que serve realmente?


124

Têm tentado encontrar uma boa descrição do que o next()método faz. Na documentação do Express, diz que next('route')pode ser usado para pular para essa rota e pular todas as rotas no meio, mas às vezes nexté chamado sem argumentos. Alguém sabe de um bom tutorial etc que descreve a nextfunção?

Respostas:


160

next()sem argumentos diz "brincando, eu realmente não quero lidar com isso". Ele volta e tenta encontrar a próxima rota que corresponda.

Isso é útil, digamos, se você deseja ter algum tipo de gerenciador de páginas com slugs de URL, além de muitas outras coisas, mas aqui está um exemplo.

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

Esse código inventado deve verificar um banco de dados em busca de uma página com uma determinada lesma de identificação. Se encontrar um, renderize-o! se não encontrar um, ignore esse manipulador de rota e verifique outros.

Portanto, next()sem argumentos, você pode fingir que não lidou com a rota para que outra coisa possa buscá-la.


Ou um contador de visitas com app.all('*'). O que permite que você execute algum código de configuração compartilhado e depois passe para outras rotas para fazer algo mais específico.

app.all('*', function(req, res, next){
  myHitCounter.count += 1;
  next();
});

app.get('/other_routes', function() {
  //...
});

Ótima resposta! Eu já vi alguns outros usos de next também, por exemplo, next (err) e next ('route'). Você tem agora o objetivo disso, quando deseja propagar um erro e quando deseja pular para uma determinada rota?
Andreas Selenwall 30/10/12

8
O @AndreasSelenwall next('route')é específico app.VERB()e é usado quando uma rota possui vários retornos de chamada para " ignorar o (s) retorno (s) de retorno de rota restante (s). " next(err)É usado para pular para qualquer " erro de middleware " ( Eda postagem).
Jonathan Lonowski

5
Votado. Apenas para esta frase: "brincando, eu realmente não quero lidar com isso", você me fez entender o que eu estava procurando. Vi muitas perguntas semelhantes e encontrei a solução em uma frase.
Pedro Barros

8
Chamar next()sem argumentos realmente não diz ao sistema "não quero lidar com isso", apenas diz ao sistema para continuar processando todos os middlewares restantes após a conclusão deste. Não é uma condição de erro para chamar next(), é parte do fluxo normal. Se você não ligar, next()nenhuma outra rota será processada.
d512 08/09/19

1
Eu gostaria que mais respostas neste site fossem escritas para o leigo ... 'next () sem argumentos diz "brincando, eu realmente não quero lidar com isso"' - Perfeito para noobs ... (@ d512 tem um melhor explicação embora)
daCoda 10/11

129

Na maioria das estruturas, você recebe uma solicitação e deseja retornar uma resposta. Devido à natureza assíncrona do Node.js, você encontra problemas com retornos de chamada aninhados se estiver fazendo coisas não triviais. Para impedir que isso aconteça, o Connect.js (antes da v4.0, o Express.js era uma camada sobre o connect.js) possui algo chamado middleware, uma função com 2, 3 ou 4 parâmetros.

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

Seu aplicativo Express.js é uma pilha dessas funções.

insira a descrição da imagem aqui

O roteador é especial, é o middleware que permite executar um ou mais middlewares para um determinado URL. Portanto, é uma pilha dentro de uma pilha.

Então, o que faz o próximo? Simples, ele diz ao seu aplicativo para executar o próximo middleware. Mas o que acontece quando você passa algo para o próximo? O Express abortará a pilha atual e executará todo o middleware que possui 4 parâmetros.

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

Este middleware é usado para processar quaisquer erros. Eu gosto de fazer o seguinte:

next({ type: 'database', error: 'datacenter blew up' });

Com esse erro, provavelmente diria ao usuário que algo deu errado e registrei o erro real.

function (err, req, res, next) {
   if (err.type === 'database') {
     res.send('Something went wrong user');
     console.log(err.error);
   }
};

Se você imaginar seu aplicativo Express.js como uma pilha, provavelmente será capaz de corrigir muita estranheza. Por exemplo, quando você adiciona o middleware do Cookie após o roteador, faz sentido que suas rotas não tenham cookies.


3
Onde você armazenaria essa função de registro anônimo?
dennismonsewicz 26/09/14

"O Express abortará a pilha atual e executará todo o middleware que possui 4 parâmetros." Eu queria saber como o Express é capaz de executar middlewares manipuladores de erro exato. Obrigado!
Abhishek Agarwal

75

IMHO, a resposta aceita para esta pergunta não é realmente precisa. Como outros já declararam, trata-se realmente de controlar quando o próximo manipulador da cadeia é executado. Mas eu queria fornecer um pouco mais de código para torná-lo mais concreto. Digamos que você tenha este aplicativo expresso simples:

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

Se você fizer

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

você verá isso impresso no console:

before request handler
handling request
after request handler

Agora, se você comentar a chamada para next()no manipulador do meio, desta forma:

app.get('/user/:id', function (req, res, next) {
    console.log('handling request');
    res.sendStatus(200);
    //next();
});

Você verá isso no console:

before request handler
handling request

Observe que o último manipulador (aquele que imprime after request handler ) não é executado. Isso ocorre porque você não está mais dizendo ao express para executar o próximo manipulador.

Portanto, realmente não importa se o manipulador "principal" (aquele que retorna 200) foi bem-sucedido ou não, se você deseja que o restante do middleware seja executado, é necessário ligar next().

Quando isso seria útil? Digamos que você deseja registrar todas as solicitações recebidas em algum banco de dados, independentemente de a solicitação ter ou não sido bem-sucedida.

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

Se você deseja que o segundo manipulador seja executado, é necessário chamar next()o primeiro manipulador.

Lembre-se de que o nó é assíncrono, portanto, não pode saber quando o retorno de chamada do primeiro manipulador foi concluído. Você precisa contar ligando next().


Sonfar a melhor resposta para mim.
Norayr Ghukasyan

Bem explicação!
Chang

7

next () sem parâmetro chama o próximo manipulador de rota OU o próximo middleware na estrutura.


2
Ou o próximo middleware.
robertklep

1

Significa simplesmente passar o controle para o próximo manipulador.

Felicidades


1

Observe a chamada acima para a próxima (). A chamada dessa função chama a próxima função de middleware no aplicativo. A função next () não faz parte da API Node.js ou Express, mas é o terceiro argumento que é passado para a função middleware. A função next () pode ser nomeada como qualquer coisa, mas por convenção, é sempre chamada de "next". Para evitar confusão, sempre use esta convenção.


0

Também foi feita uma pergunta sobre o uso do próximo ('rota'), que parece estar coberto semanalmente nas respostas fornecidas até o momento:

  1. USO DO próximo ():

Em resumo: próxima função de middleware.

Extraia desta documentação oficial do Express JS - página 'writing-middleware' :

"A função de middleware myLogger simplesmente imprime uma mensagem e passa a solicitação para a próxima função de middleware na pilha chamando a função 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)

Esta página da documentação do Express JS indica "Se a função atual do middleware não encerrar o ciclo de solicitação-resposta, ela deverá chamar next () para passar o controle para a próxima função do middleware. Caso contrário, a solicitação será interrompida".

  1. UTILIZAÇÃO DO próximo ('rota'):

Em resumo: próxima rota (vs. próxima função de middleware no caso de next ())

Extraia desta documentação do Express JS - página 'using-middleware' :

"Para pular o restante das funções de middleware de uma pilha de middleware de roteador, chame next ('route') para passar o controle para a próxima rota . NOTA: next ('route') funcionará apenas nas funções de middleware carregadas usando o funções app.METHOD () ou router.METHOD ().

Este exemplo mostra uma sub-pilha de middleware que lida com solicitações GET para o caminho / user /: id. "

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 () é o argumento de retorno de chamada para a função de middleware com req e res sendo os argumentos de solicitação e resposta http para o próximo no código abaixo.

app.get ('/', (req, res, next) => {next ()});

Então next () chama a função passada no middleware. Se a função atual do middleware não encerrar o ciclo de solicitação-resposta, ela deverá chamar next (); caso contrário, a solicitação será interrompida e atingirá o tempo limite.

next () fn precisa ser chamado dentro de cada função de middleware quando várias funções de middleware são passadas para app.use ou app.METHOD; caso contrário, a próxima função de middleware não será chamada (caso sejam passadas mais de 1 funções de middleware). Para ignorar a chamada das funções restantes do middleware, chame next ('route') dentro da função middleware, após o qual nenhuma outra função do middleware deve ser chamada. No código abaixo, fn1 será chamado e fn2 também será chamado, pois next () é chamado dentro de fn1. No entanto, fn3 não será chamado, pois next ('route') é chamado dentro de fn2.

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();
})
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.