No exercício anterior,
aprendemos sobre dois novos aspectos do JavaScript,
seu suporte para funções de primeira classe e fechamentos.
Também vimos como Node lida com o aspecto de programação assíncrona e como Node
suporta execução assíncrona de código com
o uso de retornos de chamada e também manipulação de erros.
Vejamos um exemplo de como fazemos uso disso
dentro do nosso aplicativo Node neste exercício.
Continuando com onde paramos no exercício anterior,
agora vou modificar o módulo Node retângulo, para
que ele possa ter a ajuda de callbacks.
Então eu vou remover essas exportações aqui,
e em vez disso, eles vão modificar essa função.
Vou fazer uso dessas duas funções um pouco mais tarde,
então é por isso que estou salvando-as na parte inferior.
Então deixe-me mantê-los de lado.
E então eu vou modificar este módulo retângulo da seguinte forma.
Então vamos dizer module.exports.
Então estamos usando a maneira padrão que o módulo é tratado.
E isso vai exportar esta função que leva esses três parâmetros,
x e y e callback.
O retorno de chamada é uma função que vai ser fornecida em quando este módulo é chamado.
Então este é o uso das funções de primeira classe que falamos anteriormente.
Então, dentro deste callback,
assim você pode ver que você está recebendo dois parâmetros, x e y.
neste caso, para
o retângulo, o x e y correspondem ao comprimento e largura
do retângulo que está sendo passado como os dois valores.
Então aqui dentro, vamos verificar
se x é menor que ou igual a zero ou y é menor ou igual a zero.
Temos um código como este aqui.
Então eu só vou copiar este código daqui
e depois trazê-lo para aqui e depois vamos editar.
Então, neste caso, isto é se x é
menor que ou igual a zero ou y é menor ou igual a zero.
Neste caso, o que fazemos?
Neste caso, observamos que
as dimensões do retângulo são menores ou iguais a zero.
Então temos que lidar com isso de forma diferente,
e faremos a outra parte.
A outra parte onde lidamos com a situação em que o retângulo é um retângulo válido.
Então, neste caso,
o que vamos fazer é então usar um setTimeout.
Então aqui, eu estou simulando o fato de que o que
está sendo feito neste retângulo vai levar algum tempo.
Então este é o processamento assíncrono.
Agora, uma vez que eu não tenho muito trabalho para fazer em segundo plano,
então eu vou simular isso simplesmente usando
a função setTimeout de JavaScript e, em seguida,
atrasar antes que a função de retorno de chamada seja chamada.
Então, a maneira como eu organizo isso é a seguinte.
Então, dentro do setTimeout,
eu vou chamar essa função lá
e organizar um atraso de
2.000 milissegundos ou dois segundos após o qual esta função vai ser chamada.
Então, se você lembrar,
o setTimeout que é suportado em JavaScript,
ele toma como primeiro parâmetro uma função e
o segundo parâmetro seria o período de tempo para o qual isso vai ser adiado.
Então deixe-me indentar isso.
Agora, eu preciso preencher esta função aqui.
Então eu comecei com a função seta aqui
que não leva parâmetros e, em seguida, quando não é chamado,
eu vou emitir uma chamada para o retorno de chamada.
Este callback é uma função de callback que
vai ser passada como o terceiro parâmetro aqui.
Esta função de retorno de chamada, como você notou, leva dois parâmetros.
O primeiro é o erro e o segundo é o valor de retorno.
Então, neste caso, uma vez que temos um erro,
porque x é menor ou igual a zero e y é menor ou igual a zero,
então o primeiro valor que eu vou passar como novo erro,
e esse erro é exatamente essa string que eu estava usando no console.log então,
e é isso que eu vou passar como o erro aqui.
Deixe-me agora excluir esse console.log,
eu não preciso mais dele.
Então, para o retorno de chamada,
eu vou gerar um novo objeto de erro e,
em seguida, passar isso como o valor de retorno para a função de retorno de chamada, o primeiro parâmetro.
Então eu vou dizer que dimensões retangulares devem ser maiores que zero.
Então vamos dizer l,
este é o x e o valor y que temos como os valores de entrada lá.
Então essa é a chamada de volta.
E a segunda parte deste retorno de chamada,
eu vou passar como nulo porque isso vai retornar um erro.
Então, quando você retornar um erro como o primeiro parâmetro,
o segundo parâmetro será ignorado quando esse callback foi recebido apenas
pelo módulo nó de onde estamos chamando essa função particular lá.
Então, com esse arranjo,
tão menor que zero,
então deixe-me dar algum espaço aqui para que ele seja devidamente recuado aqui.
Então, a maneira que eu estou organizando isso
aqui é que se x é menor que zero e y é menor que zero,
eu vou chamar de volta a função callback que foi passada em,
mas o primeiro parâmetro irá passar em
erro porque aqui nós percebemos que há um erro,
e o segundo parâmetro será nulo.
Se este não for o caso,
então eu vou chamar o mesmo retorno de chamada,
mas com o primeiro parâmetro.
Então deixe-me copiar esse código aqui.
Eu ainda vou usar o SetTimeout aqui.
Mas essa primeira parte não vai ser um erro,
em vez disso, a primeira parte,
neste caso, não há erro.
Então eu vou apenas passar de volta esse valor como nulo.
Então isso significa que o erro é definido como nulo.
Então este é um retângulo válido.
Então podemos calcular os valores para o retângulo.
Mas em vez disso, eu vou simplesmente passar em
um objeto JavaScript contendo as duas funções
como os dois valores dentro deste objeto JavaScript.
Então, aqui eu vou pegar esses dois,
o perímetro e a área,
e então esses dois serão passados como os dois valores aqui,
perímetro e área.
E esses dois, uma vez que eles são um objeto JavaScript,
então perímetro e área serão
as duas propriedades que eu passarei dentro desses objetos JavaScript,
e é isso.
Então aqui, no segundo caso,
o erro é definido como nulo porque não há erro,
mas a segunda parte,
observe que estou passando em um objeto JavaScript contendo duas propriedades,
perímetro e área, que são duas funções aqui.
Assim, as duas funções são a função de perímetro e a função de área.
Portanto, este objeto JavaScript será passado de volta como
o valor de retorno para o callback aqui, o segundo valor.
E novamente, eu vou atrasar isso por
um intervalo de dois segundos antes que o valor seja repassado por esta função.
A razão pela qual eu estou usando o setTimeout é para simular
um atraso antes que o retorno de chamada venha do outro lado.
Então esse tipo de representa situações em que, por exemplo,
você emite uma chamada de banco de dados para o banco de dados,
e o banco de dados precisa ser lido antes que o valor seja passado de volta para você.
Então isso vai levar uma certa quantidade de tempo.
Então eu estou basicamente simulando isso neste momento usando a função setTimeout aqui.
Mais tarde, você verá que quando integrarmos o MongoDB com
nosso Express nos exercícios posteriores,
esse atraso teria que ser simulado,
ele será automaticamente causado pelo fato de que você precisa fazer
operações de banco de dados nos bastidores antes dos dados serem obtidos.
Então aqui, tendo concluído esta atualização de módulos retangulares,
então aqui você vê que o módulo retângulo leva em
três parâmetros como é uma chamada de entrada aqui,
x, y e callback.
E assim, o retorno de chamada é a função de retorno de chamada que está sendo fornecida aqui.
E esta função de retorno de chamada será chamada dentro daqui,
e quando a função de retorno de chamada é chamada,
ou você passa de volta um erro ou você passa de volta
uma função que permite que você calcule o perímetro e a área do retângulo.
Agora, este padrão de chamar e passar em uma função de retorno de
um módulo de nó e, em seguida, o segundo módulo de nó que quando ele for concluído,
irá passar de volta o resultado usando a função de retorno de chamada é
exatamente o padrão que você verá muitas vezes repetido em aplicativos de nó.
Então essa é a razão pela qual eu estou ilustrando isso.
Claro, este é um exemplo inventado que estou ilustrando aqui, mas mostra
todos os padrões padrão que você usará com
funções de nó e callback e também a manipulação de erros.
Agora, nós atualizamos o módulo de retângulo aqui.
Vamos corrigir esse arquivo index.js para que ele possa passar na função de retorno de chamada e, em
seguida, manipular o valor de retorno que é enviado de volta do módulo de retângulo.
Voltando para index.js,
agora vamos atualizar o arquivo index.js da seguinte forma.
Em vez disso, vou remover isso do arquivo index.js.
Aqui, o que vamos acabar fazendo é chamar
este módulo retângulo e
, em seguida, passar no l e o b como os dois parâmetros.
E o terceiro parâmetro que vou passar é aquela função de retorno de chamada.
Assim, a função de retorno de chamada tem dois parâmetros, err e retângulo.
E esta função de retorno de chamada é implementada da seguinte forma aqui.
Então aqui, você vê que eu estou chamando
este módulo de nó retangular e eu estou
passando no comprimento e na largura dos dois primeiros parâmetros.
E o terceiro parâmetro é, claro,
uma função de retorno de chamada que estou implementando aqui.
Então, esta é uma função de seta que estou implementando aqui.
Então, dentro desta função de retorno de chamada,
como faço para lidar com o valor de retorno?
Então, aqui eu vou dizer se (err),
então, se o valor do erro for retornado para você,
então eu vou simplesmente fazer console.log e eu vou dizer
“ERROR” e, em seguida, o segundo valor é err.message.
Lembre-se que no retângulo,
nós criamos este novo objeto de erro
e, em seguida, passamos nesta string dentro deste objeto de erro.
Essa string será anexada
ao objeto error para a propriedade message do objeto error aqui.
Então, no arquivo index.js,
então eu estou recuperando a propriedade message do objeto de erro
e, em seguida, imprimindo no meu console aqui.
Então, se ocorrer um erro,
vou imprimir a mensagem de erro usando isso.
E assim, é assim que eu iria lidar com o erro que foi retornado por uma função de retorno de chamada.
Caso contrário, é claro que neste caso,
o módulo de retângulo retornou a função de retângulo,
o objeto que contém o perímetro e as funções de área, para que
eu possa ir em frente e imprimir esse valor.
Então aqui, eu vou dizer a área do retângulo
de dimensões l igual a,
então eu vou dizer,
e b igual a.
A razão pela qual estou a identificá-lo
explicitamente ficará muito clara quando executarmos este exemplo.
Eu digo que é retângulo.area.
Agora, observe que para esta área,
eu não estou enviando nenhum parâmetro aqui porque vai para valores,
o comprimento e a respiração já foram passados aqui no l e b,
e aqueles já estariam disponíveis para este
e aqui por causa do fechamento que JavaScript suporta.
Porque estes x e y vieram como os parâmetros,
então aqueles serão acessíveis ali mesmo nesta função callback.
Então esses x_y estarão automaticamente disponíveis para nós aqui.
Então, como uma questão de fato,
eu não preciso fornecer esses parâmetros x e y aqui em tudo porque
aqueles x e y serão recuperados deste x e y ali mesmo.
Então eu nem preciso passar esses dois valores aqui.
Então é por isso que, ali mesmo,
eu posso chamar retangle.area.
E este cálculo de área irá automaticamente obter o l e b que foram passados
pela chamada retangular para o módulo de nó direto anteriormente.
Então este é o fechamento do JavaScript operando aqui.
Então, esse é o primeiro.
Estou imprimindo a área do retângulo.
A mesma coisa, deixe-me também imprimir os perímetros.
Então, para imprimir os perímetros,
então eu vou dizer console.log.
O perímetro do retângulo será perímetro retangular.
Agora, devo dizer que esse tipo de abordagem para implementação requer um pouco
de esforço para entender e internalizar a capacidade de função assíncrona.
Leva algum tempo para você entender completamente como ele realmente funciona.
Agora, para ilustrar o fato de que
esta chamada de função resultará em uma chamada para o módulo Node,
mas esta parte será executada somente após
um atraso de dois segundos por causa do fato de que estamos usando a marca de tempo definida.
Agora, como estudamos na operação assíncrona,
porque mudamos o processamento para a parte de trás,
deixe-me também introduzir mais um console.log aqui para fazer um ponto.
Então vamos dizer que esta declaração é
depois da chamada para rect.
A razão pela qual estou ilustrando este ponto é que quando você emitir esta chamada,
este código não será executado até depois de um atraso de dois segundos.
Então, enquanto isso,
sua função, principal função aqui,
continuará e, em seguida, executar a próxima linha de código que você vê aqui.
Então esta é a continuação que vocês verão aqui.
Então, com essas alterações,
vamos salvar as alterações e, em seguida, olhar para como este aplicativo é executado agora.
Então guardando as mudanças.
Vamos para o terminal e executar este aplicativo de nó.
Agora, indo para o terminal, adicione o prompt.
Deixe-me digitar npm start e você notará imediatamente
que a resolução e esta declaração foram impressas anteriormente.
E depois desse certo atraso,
a área e o perímetro foram impressos.
Portanto, esse é um atraso de dois segundos que introduzimos usando o tempo limite estabelecido.
Então, você notou que na versão anterior,
isso foi impresso e imediatamente a área e o perímetro foram impressos logo abaixo disso.
Mas agora, observe que esses valores são impressos um pouco mais tarde.
Então, no meio, suas chamadas de função com os diferentes parâmetros que já foram
dentro e, em seguida, os retornos de chamada são chamados de volta após dois segundos de atraso para cada um deles.
E por causa do fato de que há o fechamento que o JavaScript suporta,
então os valores que são passados são preservados.
E assim, quando a função de retorno de chamada é chamada,
o valor apropriado é impresso.
Então é por isso que você vê que a área e
o perímetro são impressos corretamente e estes dois aqui,
estas duas declarações aqui,
correspondem a esta chamada particular para dirigir
com l é igual a dois e b é igual a quatro.
E então esses dois,
o próximo a dois, é claro,
correspondem a este particular e aos restantes como você vê aqui.
Então, o que eu queria ilustrar é o fato de que quando você faz a computação assíncrona,
a computação assíncrona leva seu próprio tempo
para retornar o valor enquanto sua computação principal
prosseguirá sem esperar que o retorno de chamada seja concluído.
Então, quando você precisa fazer uma certa quantidade de trabalho,
você passou como um retorno de chamada para esse outro módulo.
E quando esse outro módulo concluir seu trabalho,
ele vai chamar de volta e então esse código será executado.
Portanto, esse é o ponto que eu ilustrei usando este exemplo.
Novamente, como eu disse,
isso requer um pouco de imaginação e compreensão
para você internalizar a maneira como isso funciona,
mas você verá que com Node e também Express e quando usamos MongoDB,
você verá esse tipo de padrão repetindo muitas vezes na maneira como escrevemos nosso código.
Assim, com esta ilustração simples de retornos de chamada e manipulação de erros,
concluímos este exercício.
Este é um bom momento para você fazer um comentário get com essa mensagem,
nó, callbacks, e manipulação de erros.