Primeiro, percebo que estou atrasado em responder a essa pergunta.
Antes de discutirmos síncrono e assíncrono, vejamos brevemente como os programas são executados.
No caso síncrono , cada instrução é concluída antes da execução da próxima instrução. Nesse caso, o programa é avaliado exatamente na ordem das instruções.
É assim funciona assíncrono em JavaScript. Existem duas partes no mecanismo JavaScript, uma parte que analisa as operações de código e enfileiramento e outra que processa a fila. O processamento da fila ocorre em um encadeamento, é por isso que apenas uma operação pode acontecer por vez.
Quando uma operação assíncrona (como a segunda consulta ao banco de dados) é 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 é concluída. A fila já pode ter muitas operações. A operação na frente da fila é processada e removida da fila. Depois que a operação da consulta ao banco de dados é processada, a solicitação é enviada ao banco de dados e, quando concluída, o retorno de chamada será executado na conclusão. No momento, o processador de filas que "manipulou" a operação passa para a próxima operação - nesse caso
console.log("Hello World");
A consulta ao banco de dados ainda está sendo processada, mas a operação console.log está na frente da fila e é processada. Sendo uma operação síncrona executada imediatamente, resultando imediatamente na saída "Hello World". Algum tempo depois, a operação do banco de dados é concluída, somente então o retorno de chamada registrado com a consulta é chamado e processado, configurando o valor do resultado da variável para linhas.
É possível que uma operação assíncrona resulte em outra operação assíncrona, essa segunda operação seja 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 ela é concluída.
Um método simples de saber qual operação JavaScript é assíncrona é observar se é necessário 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 da pergunta, podemos ver apenas o segundo caso com retorno de chamada, portanto, é 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 saber mais, leia sobre promessas. As promessas são outra maneira pela qual o resultado de uma operação assíncrona pode ser tratado. O bom das promessas é que o estilo de codificação parece mais com código síncrono.
Muitas bibliotecas, como o nó 'fs', fornecem estilos síncrono e assíncrono para algumas operações. Nos casos em que a operação não leva muito tempo 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.