Iniciante no node.js, qual é a vantagem obtida usando retornos de chamada sobre eventos?

24

Eu sou um JavaScripter iniciante e não tenho conhecimento real do que acontece dentro do mecanismo V8.

Dito isso, estou gostando muito das minhas primeiras incursões no ambiente node.js., mas acho que estou constantemente usando events.EventEmitter () como um meio de emitir eventos globais para que eu possa estruturar meus programas para caber em um observador-observador padrão semelhante ao que eu escreveria, digamos, um programa Objective-C ou Python.

Encontro-me sempre fazendo coisas assim:

var events = require('events');

var eventCenter = new events.EventEmitter();

eventCenter.on('init', function() {
    var greeting = 'Hello World!';
    console.log('We're in the init function!);
    eventCenter.emit('secondFunction', greeting);
});

eventCenter.on('secondFunction', function(greeting) {
        console.log('We're in the second function!);
        console.log(greeting);
    eventCenter.emit('nextFunction');
});

eventCenter.on('nextFunction', function {
    /* do stuff */
});

eventCenter.emit('init');

Portanto, na verdade, estou apenas estruturando o código 'async' node.js no código que faz as coisas na ordem que eu esperava; em vez disso, estou meio que "codificando para trás", se isso faz sentido. Haveria alguma diferença em fazer isso de uma maneira pesada de retorno de chamada, tanto em termos de desempenho quanto em termos de filosofia? É melhor fazer a mesma coisa usando retornos de chamada em vez de eventos?

Jog
fonte
Se você acha que a legibilidade do seu código está sofrendo devido ao uso intenso de retornos de chamada, considere usar uma estrutura para encerrar o uso de retornos de chamada. É preciso um pouco de ajuste, mas as promessas geralmente podem desembaraçar os retornos feios. Se você estiver usando JQuery, poderá usar Adiado . Uma das estruturas de promessa mais simples é o RSVP .
23713 Brian Brian
Estou confuso, não vejo nada assíncrono no seu código, apenas chamadas de função escritas de maneira muito complicada.
svick

Respostas:

27

O bom dos retornos de chamada é que não há um estado global lá, e passar parâmetros para eles é trivial. Se você tem uma função download(URL, callback: (FileData)->void), pode saber que é uma função de ordem superior autônoma que essencialmente permite construir uma função "pegue isso e faça isso". Você pode ter certeza de que seu fluxo de código está exatamente como o esperado, porque ninguém mais tem controle sobre esse retorno de chamada e esse retorno de chamada não sabe nada além dos parâmetros fornecidos pela função pai. Isso o torna modular e fácil de testar.

Se você agora deseja baixar 5 arquivos em paralelo e fazer coisas diferentes, precisará disparar apenas cinco dessas funções com as funções de retorno de chamada apropriadas. Em um idioma com boa sintaxe de função anônima, isso pode ser incrivelmente poderoso.

Os eventos, por outro lado, são mais projetados para notificar os 1..*usuários sobre alguma mudança de estado. Se você disparar um evento "download concluído" no final de download(URL), que é iniciado processDownload()e sabe onde encontrar os dados, você está vinculando suas implementações de coisas a uma quantidade maior de estado. Como você paralela os downloads agora? Como você lida com os diferentes downloads de maneira diferente? É download(URL, eventId)elegante? É downloadAndDoThing(URL)elegante? Dificilmente.

Obviamente, como em todas as coisas, você está fazendo trocas. Callbacks aninhados pode fazer a ordem de execução de código mais confuso, ea falta de fácil acessibilidade mundial torna uma má escolha para qualquer coisa que você faça ter uma 1..*relação entre produtor e consumidor. Você tem mais dificuldade em passar dados, mas se você pode se safar por não ter um estado adicional, isso geralmente é um benefício.

Independentemente. Você está codificando no node.js, onde os retornos de chamada são idiomáticos, e o idioma e as bibliotecas são projetados para serem usados. Se você vê vantagens em um design ou em outro, acho que quase sempre é verdade que escrever código idiomático em qualquer idioma terá um suporte muito maior e tornará sua vida muito mais fácil do que tentar contorná-lo.

Phoshi
fonte
2

Eu nunca usei eventos no NodeJS, mas geralmente o que eu uso para eventos JS do lado do cliente é sinalizar que algo aconteceu, por exemplo, um AppointmentBookedEvent, para que diferentes partes de uma exibição do SPA possam reagir a isso (mostrá-lo em uma linha do tempo, carregá-lo em um painel, etc).
Mas usar eventos para sinalizar que um método foi concluído pode ser um caminho perigoso para se percorrer. Você não pode confiar nos eventos para chegar na mesma ordem em que foram disparados, o que pode levar a todos os tipos de aleatoriedade ...
Não há nada de errado em usar eventos, mas há um certo nível de granularidade que você não deve seguir ; se você se apegar a eventos de domínio, tudo bem. Mas notificar que os métodos foram concluídos é muito granular.

Stefan Billiet
fonte
0

Algo que você pode explorar é o uso dos eventos fora do objeto que os está emitindo. No seu exemplo, eventCenterparece emitir e manipular seus próprios eventos. Considere como a estrutura do seu aplicativo pode mudar se outros objetos começarem a manipular os eventos.

Portanto, eventCenterpode emitir "init", que outros objetos poderiam manipular para fazer o código de inicialização etc.

Dan1701
fonte