Uma discussão sobre módulos de nó está incompleta
sem falar sobre retornos de chamada e manipulação de erros.
O que são retornos de chamada e por que eles são essenciais para
suportar computação assíncrona que é muito
útil quando escrevemos aplicativos Node.js?
Como o tratamento de erros é feito em aplicativos Node?
Vamos falar brevemente sobre isso nesta palestra.
Antes de prosseguir para falar sobre Node Modules e Callbacks,
precisamos entender duas características salientes sobre a própria linguagem JavaScript.
Em primeiro lugar, JavaScript suporta o que é chamado de funções de primeira classe.
O que queremos dizer com funções de primeira classe?
É que uma função pode ser tratada como qualquer outra variável.
E, portanto, as funções podem ser passadas como
parâmetros dentro de chamadas de função para outras funções.
E isso essencialmente nos permite enviar funções como funções de retorno de chamada que podem ser
chamadas de outro módulo Node, a fim de obter algum trabalho realizado.
Em seguida, veja como isso é muito útil no suporte de retornos de chamada em Node.js.
O segundo aspecto sobre JavaScript é o suporte para Closures.
O que queremos dizer com Closures?
Especialmente, se você estiver familiarizado com linguagens de programação funcionais,
você entende como o fechamento funciona.
Uma função definida dentro de outra função
automaticamente obtém acesso às variáveis que são declaradas na função externa.
Assim, mesmo que a função externa seja concluída
a execução, quando a função interna for executada posteriormente, a função interna ainda terá acesso
aos valores das variáveis dentro dessa função externa.
E isso é novamente,
muito efetivamente usado quando usamos Callbacks em aplicativos Node.
Se você estiver acostumado com a maneira padrão de escrever aplicativos,
então você está familiarizado com a computação síncrona onde você
especifica um cálculo como um conjunto de etapas a serem feitas uma após a outra.
Agora, se você organizar sua computação da seguinte forma,
como mostrado no lado esquerdo do slide aqui,
nós temos computação um, seguido por uma computação de longa duração,
seguido por computação dois, e computação três.
Então, neste arranjo,
vamos supor que a computação dois é dependente
da computação de longa duração completando seu trabalho,
então faz sentido para a computação dois esperar até que
a computação de longa execução seja concluída antes de ser executada.
Agora, nós podemos ter outro pedaço de trabalho a
ser feito que é definido pela computação três.
Cálculo três pode ser de forma alguma dependente da computação dois,
ou a computação de longa duração para ser concluída antes de ser executada.
Então, neste caso,
se fizermos a execução síncrona desta
computação, então a computação três ficará presa,
mesmo que não seja de maneira dependente da conclusão da computação dois,
ou da computação de longa duração.
Assim, a quantidade de trabalho a ser feito pela computação três,
será adiada por nenhuma razão própria, certo?
Em vez disso é adiada por causa de algo que o precede na sequência de computação.
Agora, computação
assíncrona, podemos reorganizar este trabalho de tal forma que o cálculo um, quando ele for concluído,
pode gerar aqueles cálculos de longa execução para ser feito nos bastidores de forma independente,
e uma vez que a computação dois é dependente da computação de longa execução para terminar,
então a computação dois pode ser executada quando a computação de longa duração é concluída.
Agora, isso libera computação três para continuar,
logo após o cálculo um terminar.
Então esta maneira de organizar,
garante que a computação três terminará muito mais rápido do que
ficar preso atrás da computação de longa duração, e computação dois.
Portanto, esta abordagem de reorganizar seu trabalho é muito útil especialmente,
quando você tem um cálculo de longa execução especialmente,
E/S ligado computação a ser feito.
Então, neste caso, você pode gerar fora da computação vinculada de E/S,
e quando isso
for concluído, então o que precisa ser feito depois disso,
pode ser enviado para ele como um retorno de chamada.
Então, a computação dois será transformada em
um Callback e, em seguida, distribuída para a computação de longa duração.
Então, quando isso completar seu trabalho,
então ele vai chamar de volta a função que está dentro do callback.
Então, isso é aproveitado de forma muito eficaz pelo Node.js
em reorganizar a computação dentro de nossos aplicativos Node.
Agora, isso é muito,
muito útil quando olhamos para a maneira como Node.js em si é executado.
Então, como percebemos,
Node.js é organizado em um único loop de eventos de thread.
Este único loop de evento thread basicamente,
pega solicitações como eles entram e executá-lo um após o outro.
Sempre que precisar gerar uma solicitação de E/S,
a solicitação de E/S será gerada
e qualquer trabalho que precise ser feito após a conclusão da solicitação de E/S,
será colocado dentro de um retorno de chamada.
Então, quando a solicitação de E/S for concluída,
ele colocará o retorno de chamada na fila de solicitação,
e o retorno de chamada será tratado posteriormente,
pelo loop de evento.
Então, o loop de eventos é um loop de execução contínua
que basicamente pega solicitações da fila de solicitações
e, em seguida, os serviços um de cada vez.
Então, quando você pensa sobre isso,
você percebe que Node.js é um único thread,
mas ao mesmo tempo,
ele é capaz de alcançar uma taxa muito mais rápida de conclusão do trabalho,
simplesmente por causa do uso judicioso de retornos de chamada
e a execução assíncrona de solicitações de E/S,
como para arquivo acessos ou banco de dados,
ou processamento de longa execução que pode ser feito de forma independente nos bastidores.
Agora, a maneira como o loop de eventos Node.js lida com tudo isso,
é que o loop de eventos é organizado em uma seqüência de fases.
Então, como você vê no diagrama mostrado aqui,
as fases incluem manipulação de temporizador, manipulação de
retorno de chamada de E/S, então você tem ocioso, preparar, em
seguida, a pesquisa onde as solicitações de entrada para conexões ou dados são tratadas,
e, em seguida, a fase de verificação
e, finalmente, a fase de retorno de chamada de fechamento.
Agora, alguns detalhes sobre o que é feito em cada uma dessas fases estão listados no lado direito.
Na fase de temporizador,
o loop de evento manipula qualquer coisa que é acionada pela
função setTimeout () em JavaScript.
Os retornos de chamada de E/S são executados,
quase todos os retornos de chamada que voltam a ser
executados após uma solicitação de E/S serão manipulados pela fila de retornos de chamada de E/S.
Portanto, cada uma dessas fases mantém sua própria fila separada
e o loop de eventos Node.js pega solicitações de cada uma dessas filas e os manipula.
O, ocioso, prepare, destina-se ao uso interno por Node.js.
A pesquisa é onde ele recupera novos eventos de E/S a serem manipulados e, talvez,
as solicitações vindas de fora.
A fase de retorno de chamada próxima lida com quaisquer fechamentos de soquete que precisam ser manuseados, e assim por diante.
Agora, não precisamos nos preocupar muito com
todos esses detalhes se precisarmos realmente escrever um aplicativo Node.js.
Quando necessário, vamos olhar para alguns desses detalhes como e quando
é essencial para entender como nosso aplicativo Node funciona.
Mas, no momento, isso lhe dá uma visão geral
de como o loop de eventos Node.js é manipulado.
Basta dizer que esta é informação suficiente para que possamos
entender os aplicativos Node e como eles funcionam para o momento.
Se você quiser saber mais detalhes,
então eu lhe dei um link para uma descrição detalhada na
documentação Node.js que explica sobre o loop de eventos com mais detalhes.
Com esta compreensão rápida de Node,
Callbacks, e manipulação de erro,
vamos passar para o exercício,
onde vamos olhar para como um aplicativo Node pode escrito com Callbacks,
e como os erros podem ser tratados dentro de um aplicativo Node.
Veremos o uso repetido deste padrão em exercícios subsequentes,
e lições subsequentes especificamente,
quando olharmos para o Express,
e como construímos aplicativos do lado do servidor usando
o Express com mais detalhes na parte posterior deste curso.