‫Instrutor: Agora vamos dedicar um minuto para aprender sobre
‫a natureza assíncrona do Node. js,
‫que inclui tópicos absolutamente fundamentais,
‫como código síncrono, assíncrono, bloqueador
‫e não bloqueador.
‫E tudo isso será muito importante
‫para entender tudo o que está surgindo ao
‫longo desta seção.
‫Portanto, este trecho de código que escrevemos na última
‫aula, para ler um arquivo e depois salvar seu conteúdo em uma
‫variável, era de uma forma chamada síncrona,
‫o que significa simplesmente que
‫cada instrução é basicamente processada uma após a outra, linha por linha.
‫Neste exemplo, primeiro,
‫o módulo do sistema de arquivos é necessário,
‫em seguida, o arquivo é
‫lido e, em seguida, registramos o resultado no console.
‫Então você vê que cada
‫linha de código basicamente espera pelo resultado da linha anterior.
‫Agora, isso pode se tornar um
‫problema, especialmente com operações lentas,
‫porque cada linha bloqueia a execução do
‫resto do código.
‫E assim, dizemos que o
‫código síncrono também é chamado de código de bloqueio porque,
‫novamente, uma determinada operação só pode ser
‫executada após o término da anterior.
‫E por causa da forma como Node. js foi projetado,
‫isso se torna um grande problema, como veremos
‫em detalhes no próximo slide.
‫Portanto, a solução para esse
‫problema no Node é usar código assíncrono e sem bloqueio.
‫Portanto, no código assíncrono, carregamos um trabalho pesado
‫para ser basicamente trabalhado em segundo plano.
‫E então, uma vez que o trabalho
‫esteja concluído, uma função de retorno de chamada que
‫registramos antes é chamada para tratar o resultado.
‫E durante todo esse
‫tempo, o resto do código ainda pode ser
‫executado sem ser bloqueado pela tarefa pesada,
‫que agora está sendo executada em segundo plano.
‫Então, o que isso significa é que podemos efetivamente
‫adiar ou reagir no
‫futuro a fim de tornar o código
‫sem bloqueio e isso é, obviamente, muito melhor.
‫Faz sentido?
‫Portanto, neste exemplo, usamos a função
‫readFile assíncrona, que aceita uma função de retorno de chamada.
‫Isso iniciará a leitura do arquivo em
‫segundo plano e, em seguida, passará imediatamente para a próxima
‫instrução, imprimindo no console o arquivo de leitura de string.
‫Então, novamente, você vê, não estamos bloqueando a execução aqui.
‫Então, quando o arquivo finalmente for completamente lido, a
‫função de retorno de
‫chamada será chamada e, assim, os
‫dados lidos serão impressos no console.
‫Então isso é bem
‫diferente da versão síncrona, não é?
‫Agora, a questão aqui
‫é: por que realmente tem que ser assim?
‫Qual é o problema em bloquear a execução de código no Node. js?
‫Ou, em outras palavras, por que realmente usamos callback tantas
‫vezes no Node. js?
‫Bem, vamos descobrir.
‫E para entender essas questões, a primeira coisa
‫que precisamos entender é o fato de
‫que um Nodo. processo js, que
‫é onde nosso aplicativo está sendo
‫executado, há apenas um único thread.
‫E o thread é como um conjunto de instruções que
‫é executado na CPU do computador.
‫Então, basicamente, o thread é onde
‫nosso código é realmente executado no processador de uma máquina.
‫Então, lembre-se, Node. js é basicamente single-threaded
‫e, portanto, para cada aplicativo, há apenas um thread.
‫É assim que Node. js foi projetado.
‫Agora, o que isso significa é que
‫todos os usuários que acessam seu aplicativo estão todos usando o
‫mesmo thread, portanto, basicamente, acessando o mesmo thread.
‫E assim, sempre que eles estiverem interagindo com o aplicativo,
‫o código que é executado para
‫cada usuário será executado todo no mesmo thread e no mesmo
‫local no computador que executa o aplicativo.
‫E isso é verdade, não importa
‫se você tem cinco usuários, como neste diagrama, ou 5.000 ou 5 milhões.
‫Tudo bem?
‫Agora, o que isso também significa é que quando
‫um usuário bloqueia o thread único com
‫código síncrono, como acabamos
‫de ver, todos os outros usuários terão
‫que esperar que a execução termine.
‫E isso pode não ser um
‫grande problema se você tiver cinco usuários,
‫mas definitivamente será para milhares ou até milhões de
‫usuários ao mesmo tempo.
‫Então, imagine que há um usuário acessando seu aplicativo
‫e há um enorme arquivo síncrono lido em seu código
‫que levará cerca de um segundo para carregar.
‫Isso significará, é claro, que por aquele
‫segundo, todos os outros usuários
‫terão que esperar porque toda a execução é bloqueada naquele segundo.
‫Portanto, se esses outros usuários quiserem fazer algumas tarefas
‫simples, como efetuar login em
‫seu aplicativo ou apenas solicitar alguns dados, eles não poderão fazê-lo.
‫Eles terão que esperar até que a leitura do arquivo seja concluída.
‫Somente quando isso acontecer, eles finalmente poderão realizar as tarefas
‫mais simples, uma após a outra.
‫Agora, observe que esta é uma versão muito simplificada do que realmente
‫acontece nos bastidores do Node. js, é por
‫isso que voltaremos a tudo isso
‫na próxima seção e obteremos uma compreensão ainda mais
‫profunda de como o Node. js lida com código assíncrono nos bastidores.
‫Mas, neste ponto,
‫isso é o suficiente para você entender o conceito.
‫É melhor seguir passo a
‫passo aqui e não
‫confundir muito desde o início, ok?
‫De qualquer forma, é assim que
‫a situação aconteceria com o código de bloqueio
‫síncrono, o que obviamente é uma experiência terrível para seus usuários.
‫Portanto, é realmente seu trabalho como desenvolvedor
‫evitar esses tipos de situações
‫usando código assíncrono.
‫Portanto, para a mesma situação, devemos, é claro, usar
‫a função de leitura de arquivo assíncrona,
‫que em vez de bloquear
‫o thread único, faz o trabalho pesado
‫em segundo plano, onde basicamente permanece até
‫terminar de ler os dados do arquivo.
‫Obviamente, também registramos uma função de retorno de
‫chamada a ser chamada assim que os dados estiverem disponíveis.
‫E, neste cenário, todos os outros usuários
‫podem realizar suas tarefas em um único thread,
‫um após o outro, enquanto o arquivo ainda está sendo
‫lido em segundo plano.
‫Agora, uma vez que os dados são lidos, nossa função de
‫retorno de chamada, é claro, será
‫chamada para ser executada no único thread principal a fim de processar os dados lidos.
‫E é isso.
‫Essa é uma visão geral de como o Node. js lida
‫com o comportamento assíncrono para implementar o modelo
‫de E / S sem bloqueio de
‫que falamos na aula de introdução, certo?
‫E I / O significa simplesmente entrada-saída, que é
‫basicamente coisas como acessar o sistema de arquivos
‫e lidar com solicitações de rede.
‫Este é realmente o motivo pelo qual o Node. js é totalmente
‫projetado em torno de retornos de chamada,
‫como você verá ao longo do curso.
‫Em outras linguagens de programação, como PHP, funciona
‫de maneira muito diferente porque você obtém, basicamente, um
‫novo thread para cada novo usuário,
‫que é um paradigma completamente diferente
‫e realmente funciona de forma completamente diferente.
‫Mas o criador do Node. js descobriu que
‫esse modelo é a melhor solução para construir aplicativos
‫da web de alto desempenho e escalonáveis.
‫Agora, apenas como uma nota final aqui, é importante
‫saber que, quando usamos
‫callbacks em nosso código, isso não o torna automaticamente assíncrono, certo?
‫Portanto, passar funções para outras funções
‫é bastante comum
‫em JavaScript, mas é claro, novamente,
‫isso não as torna assíncronas automaticamente, certo?
‫Funciona dessa maneira apenas para algumas funções na API do Node,
‫como a função readFile e
‫muitas, muitas outras, conforme as pessoas explorarem no futuro.
‫E agora, só para terminar,
‫já que estamos falando de código assíncrono aqui,
‫apenas uma última observação sobre funções de retorno de chamada.
‫Portanto, esse modelo de retorno de chamada que acabamos
‫de discutir, em que
‫uma função é chamada assim que a anterior terminar
‫seu trabalho, pode levar rapidamente a algum código difícil de ler e não gerenciável.
‫Basta pegar este exemplo onde o segundo arquivo
‫lido depende do primeiro,
‫então, o terceiro arquivo lido depende do segundo
‫e, finalmente, queremos usar os dados finais
‫para escrever um arquivo como resultado.
‫Isso parece muito confuso, certo?
‫Quer dizer, vai funcionar muito
‫bem, mas é difícil de raciocinar e
‫isso ocorre apenas com quatro níveis de profundidade.
‫Imagine que você tivesse cerca de 10 ou 20
‫níveis, o que na verdade não é tão incomum.
‫De qualquer forma, isso é o que chamamos de inferno de callback.
‫É um problema tão
‫comum que já tem nome próprio.
‫E você percebe esta forma triangular aqui?
‫Isso é um sinal muito claro de que você está no inferno com o retorno de chamada.
‫Agora, como podemos realmente escapar do inferno de callback?
‫Bem, podemos usar ferramentas mais avançadas para
‫lidar com código assíncrono, como promessas
‫ES6 ou ainda melhor, ES8 async / await.
‫Agora, o modelo que acabamos de falar
‫ainda será o mesmo.
‫Nós apenas temos maneiras mais
‫elegantes de lidar com o próprio código e escrevê-lo.
‫E há toda uma seção opcional
‫disso mais tarde no curso sobre promessas e também, assíncrono / aguardar,
‫caso você não esteja familiarizado com eles.
‫Mas, por enquanto, continuaremos usando callbacks porque
‫é isso que o Node originalmente usava e
‫foi projetado em torno disso.
‫E agora, dito
‫isso, vamos prosseguir e usar esse modelo assíncrono
‫na prática pela primeira vez.