Novizio di node.js, qual è il vantaggio ottenuto utilizzando i callback sugli eventi?

24

Sono un debuttante JavaScripter e non ho alcuna conoscenza di cosa succede all'interno del motore V8.

Detto questo, mi sto davvero godendo le mie prime incursioni nell'ambiente node.js, ma trovo che utilizzo costantemente events.EventEmitter () come mezzo per emettere eventi globali in modo da poter strutturare i miei programmi per adattarli a schema del notificatore-osservatore simile a quello che scriverei in un programma Objective-C o Python.

Mi trovo sempre a fare cose del genere:

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');

Quindi in effetti sto solo strutturando il codice node.js 'asincrono' nel codice che fa le cose nell'ordine che mi aspetto, invece sono un po '"codificato all'indietro" se questo ha senso. Ci sarebbe qualche differenza nel fare questo in modo pesante come callback, sia per quanto riguarda le prestazioni che per la filosofia? È meglio fare la stessa cosa usando i callback al posto degli eventi?

    
posta Jog 22.11.2013 - 07:39
fonte

3 risposte

27

La cosa bella dei callback è che non c'è uno stato globale lì, e il passaggio dei parametri a loro è banale. Se hai una funzione download(URL, callback: (FileData)->void) , puoi sapere che è una funzione di ordine superiore autonoma che essenzialmente ti permette di costruire una funzione "afferra questo e fallo". Puoi essere sicuro che il tuo flusso di codice è esattamente come ti aspetti, perché nessun altro ha un handle su quel callback, e quel callback non sa nulla se non i parametri dati dalla funzione genitore. Ciò lo rende modulare e facile da testare.

Se ora si desidera scaricare 5 file in parallelo e fare cose diverse, è necessario disattivare solo cinque di queste funzioni con le funzioni di callback appropriate. In una lingua con una buona sintassi della funzione anonima, questo può essere incredibilmente potente.

Gli eventi, d'altro canto, sono più progettati per notificare agli utenti 1..* di alcuni cambiamenti di stato. Se attivi un evento "download completato" alla fine di download(URL) , che lancia processDownload() che sa dove trovare i dati, stai legando le tue implementazioni di cose a una maggiore quantità di stato. Come si parallelizzano i download ora? Come gestisci i diversi download in modo diverso? download(URL, eventId) elegante? downloadAndDoThing(URL) elegante? Quasi.

Naturalmente, come con tutte le cose, stai facendo dei compromessi. Le callback annidate possono rendere l'ordine di esecuzione del codice più confuso e la mancanza di una facile accessibilità globale lo rende una scelta sbagliata per qualsiasi cosa in cui fai abbia una relazione 1..* tra produttore e consumatore. Hai più difficoltà a trasmettere i dati, ma se riesci a farla finita con uno stato aggiuntivo, di solito è comunque un vantaggio.

A prescindere. Stai codificando in node.js dove i callback sono idiomatici e il linguaggio e le librerie sono progettati attorno al loro uso. Sia che tu veda i vantaggi in un progetto o in un altro, penso che sia quasi sempre vero che scrivere codice idiomatico in qualsiasi lingua avrà un supporto molto maggiore e rendere la tua vita molto più facile che tentare di aggirarla.

    
risposta data 22.11.2013 - 11:10
fonte
2

Non ho mai usato eventi in NodeJS, ma generalmente quello che uso gli eventi JS clientide sta segnalando che qualcosa è successo, ad es. un AppointmentBookedEvent, in modo che le diverse parti di una vista SPA possano reagire (mostrarlo in una timeline, caricarlo in un pannello, ecc.).
Ma usare gli eventi per segnalare che un metodo è stato completato può essere una strada pericolosa da percorrere. Non puoi fare affidamento sugli eventi per arrivare nello stesso ordine in cui sono stati licenziati, in modo da portare a ogni sorta di casualità ...
Non c'è niente di sbagliato nell'usare gli eventi, ma c'è un certo livello di granularità a cui non dovresti andare; se ti attacchi agli eventi domain-ish, va bene. Ma notificare che i metodi sono finiti è troppo granulare.

    
risposta data 22.11.2013 - 08:19
fonte
0

Qualcosa che potresti esplorare è l'uso degli eventi al di fuori dell'oggetto che li sta emettendo. Nel tuo esempio, eventCenter sembra sia emettere che gestire i propri eventi. Considera come la struttura della tua applicazione potrebbe cambiare se altri oggetti iniziano a gestire gli eventi.

Quindi, eventCenter potrebbe emettere "init", che altri oggetti potrebbero quindi gestire per fare il loro codice di avvio, ecc.

    
risposta data 22.11.2013 - 10:50
fonte

Leggi altre domande sui tag