Qual é a diferença entre a programação síncrona e assíncrona (em node.js)

Eu tenho lido nodebeginner E me deparei com os dois seguintes códigos.

O primeiro:

var result = database.query("SELECT * FROM hugetable"); console.log("Hello World"); 

O segundo:

  database.query("SELECT * FROM hugetable", function(rows) { var result = rows; }); console.log("Hello World"); 

Eu entendo o que eles devem fazer, eles consultam o database para recuperar a resposta para a consulta. E então console.log('Hello world') .

O primeiro deles é supostamente um código síncrono. E o segundo é um código asynchronous.

A diferença entre as duas peças é muito vaga para mim. Qual seria o resultado?

Pesquisando em programação assíncrona também não me ajudou.

A diferença é que no primeiro exemplo , o programa irá bloquear na primeira linha. A próxima linha ( console.log ) terá que esperar.

No segundo exemplo , o console.log será executado enquanto a consulta estiver sendo processada. Ou seja, a consulta será processada em segundo plano, enquanto o programa está fazendo outras coisas e, quando os dados da consulta estiverem prontos, você fará o que quiser com ela.

Então, em poucas palavras: o primeiro exemplo irá bloquear, enquanto o segundo não será.

A saída dos dois exemplos a seguir:

 // Example 1 - Synchronous (blocks) var result = database.query("SELECT * FROM hugetable"); console.log("Query finished"); console.log("Next line"); // Example 2 - Asynchronous (doesn't block) database.query("SELECT * FROM hugetable", function(result) { console.log("Query finished"); }); console.log("Next line"); 

Seria:

  1. Query finished
    Next line
  2. Next line
    Query finished

Nota
Enquanto o próprio nó é único encadeado , existem algumas tarefas que podem ser executadas em paralelo. Por exemplo, as operações do sistema de arquivos ocorrem em um processo diferente.

É por isso que o Node pode fazer operações assíncronas: um thread está fazendo operações do sistema de arquivos, enquanto o thread principal do Node continua executando seu código javascript. Em um servidor orientado a events como o Nó, o encadeamento do sistema de arquivos notifica o encadeamento do Nó principal de determinados events, como conclusão, falha ou progresso, juntamente com quaisquer dados associados a esse evento (como o resultado de uma consulta ao database ou um erro mensagem) eo thread principal do Node decide o que fazer com esses dados.

Você pode ler mais sobre isso aqui: Como o modelo de E / S único não segmentado funciona no Node.js

A diferença entre essas duas abordagens é a seguinte:

Modo síncrono: Aguarda que cada operação seja concluída, depois disso só executa a próxima operação. Para sua consulta: O comando console.log() não será executado até & a menos que a consulta tenha terminado de executar para obter todo o resultado do Banco de Dados.

Modo asynchronous: Ele nunca espera que cada operação seja concluída, em vez disso, executa todas as operações apenas no primeiro GO. O resultado de cada operação será tratado assim que o resultado estiver disponível. Para sua consulta: O comando console.log() será executado logo após o método Database.Query() . Enquanto a consulta do Banco de Dados é executada em segundo plano e carrega o resultado quando ele é concluído, recuperando os dados.

Casos de uso

  1. Se suas operações não estão fazendo muito trabalho pesado, como consultar dados enormes do database, vá em frente com o modo síncrono, de outra forma assíncrona.

  2. De maneira assíncrona, você pode mostrar um indicador de Progresso para o usuário, enquanto no fundo você pode continuar com seus trabalhos pesados. Este é um cenário ideal para aplicativos GUI.

Isso se tornaria um pouco mais claro se você adicionar uma linha aos dois exemplos:

 var result = database.query("SELECT * FROM hugetable"); console.log(result.length); console.log("Hello World"); 

O segundo:

 database.query("SELECT * FROM hugetable", function(rows) { var result = rows; console.log(result.length); }); console.log("Hello World"); 

Tente executá-los, e você notará que o primeiro exemplo (síncrono), o result.length, será impresso ANTES da linha “Hello World”. No segundo exemplo (asynchronous), o result.length será (muito provavelmente) impresso APÓS a linha “Hello World”.

Isso porque, no segundo exemplo, o database.query é executado de forma assíncrona em segundo plano, e o script continua imediatamente com o “Hello World”. O console.log(result.length) é executado apenas quando a consulta do database é concluída.

Primeiro, percebo que estou atrasado em responder a essa pergunta.

Antes de discutir síncrono e asynchronous, vamos examinar brevemente como os programas são executados.

No caso síncrono , cada instrução é concluída antes que a próxima instrução seja executada. Nesse caso, o programa é avaliado exatamente na ordem das instruções.

É assim que funciona asynchronous em JavaScript. Existem duas partes no mecanismo JavaScript, uma parte que examina as operações de código e enfileiramento e outra que processa a fila. O processamento da fila acontece em um thread, é por isso que apenas uma operação pode acontecer por vez.

Quando uma operação assíncrona (como a segunda consulta ao database) é vista, o código é analisado e a operação é colocada na fila, mas, nesse caso, um retorno de chamada é registrado para ser executado quando essa operação for concluída. A fila pode ter muitas operações já. A operação na frente da fila é processada e removida da fila. Depois que a operação da consulta do database for processada, a solicitação será enviada ao database e, quando concluída, o retorno de chamada será executado na conclusão. Neste momento, o processador de filas tendo “manipulado” a operação se move na próxima operação – neste caso

  console.log("Hello World"); 

A consulta do database ainda está sendo processada, mas a operação console.log está na frente da fila e é processada. Esta sendo uma operação síncrona é executada imediatamente resultando imediatamente na saída “Hello World”. Algum tempo depois, a operação do database é concluída, somente então o retorno de chamada registrado com a consulta é chamado e processado, configurando o valor do resultado da variável em linhas.

É possível que uma operação assíncrona resulte em outra operação assíncrona, essa segunda operação será colocada na fila e, quando chegar à frente da fila, será processada. Chamar o retorno de chamada registrado com uma operação assíncrona é como o tempo de execução do JavaScript retorna o resultado da operação quando isso é feito.

Um método simples de saber qual operação JavaScript é assíncrona é observar se ele exige um retorno de chamada – o retorno de chamada é o código que será executado quando a primeira operação for concluída. Nos dois exemplos na questão, podemos ver apenas o segundo caso tem um retorno de chamada, por isso é a operação assíncrona dos dois. Nem sempre é o caso devido aos diferentes estilos de manipulação do resultado de uma operação assíncrona.

Para aprender mais, leia sobre promises. As promises são outra maneira pela qual o resultado de uma operação assíncrona pode ser manipulado. O bom das promises é que o estilo de codificação parece mais um código síncrono.

Muitas bibliotecas, como o nó ‘fs’, fornecem estilos síncronos e asynchronouss para algumas operações. Nos casos em que a operação não demora muito e não é muito usada – como no caso de ler um arquivo de configuração – a operação de estilo síncrono resultará em um código mais fácil de ler.

No caso síncrono, o comando console.log não é executado até que a consulta SQL tenha terminado a execução.

No caso asynchronous, o comando console.log será executado diretamente. O resultado da consulta, em seguida, será armazenado pela function “retorno de chamada” algum tempo depois.

A principal diferença é com a programação assíncrona, você não interrompe a execução de outra forma. Você pode continuar executando outro código enquanto o ‘pedido’ está sendo feito.

A function torna o segundo asynchronous.

O primeiro força o programa a esperar que cada linha termine de rodar antes que a próxima possa continuar. O segundo permite que cada linha seja executada em conjunto (e de forma independente) de uma só vez.

Idiomas e frameworks (js, node.js) que permitem asynchronous ou simultaneidade são ótimos para coisas que requerem transmissão em tempo real (por exemplo, bate-papo, aplicativos de estoque).

Programação de Sincronização

Linguagens de programação como C, C #, Java são programações de synchronization, o que sempre que você escreve será executado na ordem de sua escrita.

 -GET DATA FROM SQL. //Suppose fetching data take 500 msec -PERFORM SOME OTHER FUNCTION. //Performing some function other will take 100 msec, but execution of other //task start only when fetching of sql data done (ie some other function //can execute only after first in process job finishes). -TOTAL TIME OF EXECUTION IS ALWAYS GREATER THAN (500 + 100 + processing time) msec 

Assíncrono

O NodeJs vem com um recurso asynchronous, é de natureza não-bloqueante, suponha que em qualquer tarefa de E / S que esteja demorando (buscando, escrevendo, lendo), o nodejs não ficará ocioso e esperará que a tarefa seja finalizada. Começará a executar as próximas tarefas na fila e, sempre que essa tarefa de conclusão de tarefas for concluída, ela será notificada usando o retorno de chamada. O exemplo a seguir ajudará:

 //Nodejs uses callback pattern to describe functions. //Please read callback pattern to understand this example //Suppose following function (I/O involved) took 500 msec function timeConsumingFunction(params, callback){ //GET DATA FROM SQL getDataFromSql(params, function(error, results){ if(error){ callback(error); } else{ callback(null, results); } }) } //Suppose following function is non-blocking and took 100 msec function someOtherTask(){ //some other task console.log('Some Task 1'); console.log('Some Task 2'); } console.log('Execution Start'); //Start With this function timeConsumingFunction(params, function(error, results){ if(error){ console.log('Error') } else{ console.log('Successfull'); } }) //As (suppose) timeConsumingFunction took 500 msec, //As NodeJs is non-blocking, rather than remain idle for 500 msec, it will start //execute following function immediately someOtherTask(); 

Em resumo, a saída é como:

 Execution Start //Roughly after 105 msec (5 msec it'll take in processing) Some Task 1 Some Task 2 //Roughly After 510 msec Error/Successful //depends on success and failure of DB function execution 

A diferença é clara onde a synchronization irá definitivamente levar mais de 600 (500 + 100 + tempo de processamento) mseg, async economiza tempo.