Da principiante a node.js, qual è il vantaggio ottenuto utilizzando i callback rispetto agli eventi?


24

Sono un principiante JavaScripter e non ho alcuna reale conoscenza di ciò che accade all'interno del motore V8.

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

Mi ritrovo a fare sempre 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" in codice che fa le cose nell'ordine che mi aspetto, invece sto piuttosto "codificando all'indietro" se questo ha senso. Ci sarebbe qualche differenza nel fare questo in un modo pesantemente richiamato, sia dal punto di vista delle prestazioni che dal punto di vista della filosofia? È meglio fare la stessa cosa usando i callback invece degli eventi?


Se si riscontra una sofferenza nella leggibilità del codice a causa dell'uso intenso di callback, prendere in considerazione l'uso di un framework per concludere l'uso dei callback. Ci vuole un po 'di adattamento, ma le promesse possono spesso districare brutti callback. Se stai usando JQuery, puoi usare Deferred . Uno dei più semplici framework di promesse è RSVP .
Brian,

Sono confuso, non vedo nulla di asincrono nel tuo codice, solo chiamate di funzione scritte in modo troppo complicato.
svick,

Risposte:


27

La cosa bella dei callback è che non c'è uno stato globale lì, e passare i parametri a loro è banale. Se hai una funzione download(URL, callback: (FileData)->void), puoi sapere che è una funzione autonoma di ordine superiore che ti consente essenzialmente di costruire una funzione "prendi questa e fai quella". 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 conosce altro che i parametri forniti dalla funzione genitore. Ciò lo rende modulare e facile da testare.

Se ora vuoi scaricare 5 file in parallelo e fare cose diverse, devi solo disattivare cinque di queste funzioni con le funzioni di callback appropriate. In una lingua con una buona sintassi delle funzioni anonime questo può essere incredibilmente potente.

Gli eventi, d'altra parte, sono più progettati per avvisare gli 1..*utenti di alcuni cambiamenti di stato. Se si attiva un evento di "download completato" alla fine di download(URL), che si avvia e processDownload()che sa dove trovare i dati, si stanno legando le implementazioni di cose a una maggiore quantità di stato. Come parallelizzi i download ora? Come gestite i diversi download in modo diverso? È download(URL, eventId)elegante? È downloadAndDoThing(URL)elegante? Quasi.

Naturalmente, come per tutte le cose, stai facendo dei compromessi. Callback nidificati possono fare l'ordine di esecuzione di codice più confusa, e la mancanza di facile accessibilità globale lo rende una scelta sbagliata per tutto ciò in cui si fare avere un 1..*rapporto tra produttore e consumatore. Hai più difficoltà a passare i dati in giro, ma se riesci a cavartela senza avere uno stato aggiuntivo, di solito è comunque un vantaggio.

Senza riguardo. Stai codificando in node.js in cui i callback sono idiomatici e il linguaggio e le librerie sono progettati in base al loro utilizzo. Sia che tu veda vantaggi in un disegno o in un altro, penso che sia quasi sempre vero che scrivere codice idiomatico in qualsiasi lingua avrà un supporto molto maggiore e renderà la tua vita molto più semplice che cercare di aggirare.


2

Non ho mai usato eventi in NodeJS, ma in genere quello per cui uso gli eventi JS sul lato client è segnalare che è successo qualcosa, ad esempio un AppointmentBookedEvent, in modo che parti diverse di una vista SPA possano reagire a ciò (mostrarlo in una sequenza temporale, caricarlo in un pannello, ecc.).
Ma usare gli eventi per segnalare il completamento di un metodo può essere una strada pericolosa da percorrere. Non puoi fare affidamento sugli eventi per arrivare nello stesso ordine in cui sono stati licenziati, quindi ciò potrebbe portare a tutti i tipi di casualità ...
Non c'è niente di sbagliato nell'uso degli eventi, ma c'è un certo livello di granularità che non dovresti sottoporre ; se ti attieni agli eventi di dominio, va bene. Ma informare che i metodi sono finiti è troppo granulare.


0

Qualcosa che potresti esplorare è l'uso degli eventi all'esterno dell'oggetto che li sta emettendo. Nel tuo esempio, eventCentersembra sia emettere che gestire i propri eventi. Considera come la struttura dell'applicazione potrebbe cambiare se altri oggetti iniziassero a gestire gli eventi.

Quindi, eventCenterpotrebbe emettere "init", che altri oggetti potrebbero quindi gestire per eseguire il loro codice di avvio, ecc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.