Ryan Dahl decidiu criar o Node.js após observar como uma barra de progresso que monitorava o upload de um arquivo funcionava no site Flickr. Ao fazê-lo, Dahl notou que o navegador precisava fazer consultas para o servidor, uma vez que as informações sobre o arquivo sendo enviado eram poucas.

A partir dessa experiência, Dahl começou a questionar as limitações dos servidores HTTP em gerenciar múltiplas conexões simultâneas. Ele chegou à conclusão que o modelo de programação atual, onde a instrução seguinte em um programa não é iniciada até que a anterior termine, não era o mais adequado nesse contexto.

É claro que as limitações observadas por Dahl tinham outras aplicações. Considere que desejamos buscar um conjunto de dados de um banco. Para isso poderíamos enviar uma consulta ao banco de dados, aguardar ela retornar e então realizar outras operações no código:

dados = consulta_cursos_concluidos();
   
para_cada dado em dados {
    exibir_dado(dado)
}
   
...

Em 2009, na European JSConf, Dahl apresentou a primeira versão do Node, utilizando o V8, motor de processamento de JavaScript do Google Chrome e uma API de I/O de baixo nível. Na proposta de Dahl, a entrada e saída de dados agora não mais bloqueavam a execução do programa, funcionando de forma assíncrona.

Essa mudança gerou um certo impacto na forma como escrevemos nossos códigos. Tomando como exemplo o caso anterior, no modelo do Node teríamos um problema de lógica, pois nada impediria do trecho que percorre os dados fosse executado antes da consulta ao banco ser concluída. Isso porque o processo de I/O, entrada e saída de dados, não para a execução do programa no Node.

Sendo assim, no Node devemos programar da seguinte forma:

função faça_quando_os_dados_retornarem_do_banco(dados) {
    para_cada dado em dados {
        exibir_dado(dado)
    }
}
   
consulta_cursos_concluidos(faça_quando_os_dados_retornarem_do_banco);
...

Nesse novo exemplo, uma função é passada por callback ou como parâmetro para aquela que realiza a consulta no banco de dados. Internamente, a função que consulta os dados passará os mesmos para a função callback, que por sua vez executará a sua própria rotina de exibição. Aqui pensamos primeiro no que gostaríamos de fazer antes de como fazer e essa é uma mudança significativa no modelo de programação.