Entendendo o middleware pattern em Node.js | iMasters
A implementação representa um pipeline de processamento onde handlers, units e filters são funções. Essa funções são conectadas criando uma sequência de processamento assíncrona que permite pré-processamento, processamento e pós-processamento de qualquer tipo de dado. Uma das principais vantagens desse pattern é a facilidade de adicionar plugins de maneira não intrusiva.
Novos middlewares podem ser invocados usando a função use() (o nome não precisa ser estritamente use, aqui estamos usando o express como base)
Geralmente novos middlewares são adicionados ao final do pipeline, mas essa não é uma regra obrigatória
Quando um novo dado é recebido para processamento, o middleware registrado é invocado em um fluxo de execução assíncrono
Cada unidade no pipeline recebe o resultado da anterior como input
Cada pedaço do middleware pode decidir parar o processamento simplesmente não chamando o callback, ou em caso de erro, passando o erro por callback. Normalmente, erros disparam um fluxo diferente de processamento que é dedicado ao tratamento de erros
Incrementar os dados com propriedades ou funções
Substituir os dados com o resultado de algum tipo de processamento
Manter a imutabilidade dos dados sempre retornando uma cópia como resultado do processamento
A implementação correta depende de como o Middleware Manager é implementado e do tipo de dados que serão processados no próprio middleware. Para saber mais sobre o pattern, sugiro a leitura do livro Node.js Design Patterns.
Agora, vamos adicionar uma mensagem no console que deve aparecer antes da mensagem da rota:
Middlewares são apenas funções que recebem os parâmetros requisição (req), resposta (res) e próximo (next), executam alguma lógica e chamam o próximo middleware chamando next. No exemplo acima, chamamos o use passando uma função que será o middleware. Ela mostra a mensagem no console e depois chama o next().
Se executarmos esse código e acessarmos a rota /, a saída no terminal será:
Ok! Mas como eu sabia que iria executar antes? Como vimos anteriormente no middleware pattern, o middleware manager executa uma sequência de middlewares, então, a ordem do use interfere na execução, por exemplo, se invertermos a ordem, como no código abaixo:
Dessa vez o nosso middleware não foi chamado. Isso acontece porque a rota chama a função res.send(), invés de next(), ou seja, ela quebra a sequência de middlewares.
Caso seja feita uma chamada para /, a saída será:
Já para /users, veremos a seguinte saída no terminal:
Apenas o primeiro middleware foi chamado; o middleware de erro não. Vamos ver o que acontece quando passamos um erro para o next do primeiro middleware.