W3docs

Callback JavaScript

In JavaScript, le callback sono un concetto essenziale che permette agli sviluppatori di gestire le operazioni asincrone in modo efficace.

Una callback è semplicemente una funzione che si passa a un'altra funzione come argomento, in modo che la funzione ricevente possa richiamarla in un secondo momento. Poiché le funzioni sono valori di prima classe in JavaScript — possono essere memorizzate in variabili, passate in giro e restituite — qualsiasi funzione può accettare un'altra funzione come parametro. Questa singola idea alimenta tutto, dai metodi degli array come map ai timer e alle richieste di rete.

Questo capitolo tratta cosa sono le callback, la differenza tra callback sincrone e asincrone, la convenzione error-first, il problema del callback hell che creano e come Promises e async/await lo risolvono.

La Prima Callback

La funzione che si passa è la callback; la funzione che la riceve e la invoca è la funzione di ordine superiore. Qui una callback viene eseguita al termine di un'operazione:

javascript— editable

finishTask viene passata a completeTask e invocata al suo interno. Nota che si passa il nome della funzione (finishTask) senza parentesi — aggiungere () la chiamerebbe immediatamente e passerebbe il suo valore di ritorno al suo posto.

Callback Sincrone vs. Asincrone

Non tutte le callback riguardano l'attesa. Esistono due tipi distinti e confonderli è una causa comune di bug.

Callback sincrone

Una callback sincrona viene eseguita immediatamente, nell'ordine, prima che la funzione esterna ritorni. I metodi degli array sono l'esempio classico:

javascript— editable

Qui transform viene chiamata e completata per ogni elemento prima che map ritorni. I metodi integrati come Array.prototype.map, filter, forEach e sort accettano tutti callback sincrone.

Callback asincrone

Una callback asincrona viene consegnata a un'operazione che si completa in seguito — un timer, una lettura di file o una richiesta di rete. La funzione esterna ritorna immediatamente e la callback si attiva una volta che il risultato è pronto. JavaScript pianifica queste operazioni tramite l'event loop, che mette in coda le callback e le esegue quando lo stack delle chiamate è vuoto.

javascript— editable

Anche con un ritardo di 0ms, la callback viene eseguita dopo il codice sincrono circostante. Questa è la caratteristica distintiva di una callback asincrona: non può restituire un valore nel modo normale, quindi l'unico modo per usare il risultato è inserire il codice di continuazione all'interno della callback. Per capire esattamente quando queste vengono eseguite, consulta JavaScript: Event Loop.

La Convenzione Error-First

Le callback asincrone non possono usare throw verso il codice che ha avviato l'operazione — nel momento in cui vengono eseguite, quel codice è già tornato da tempo. La comunità si è consolidata su una convenzione: passare l'errore come primo argomento e il risultato come secondo. La callback controlla sempre prima l'errore.

javascript— editable

Quando tutto va a buon fine, il campo dell'errore è null. Questa firma (err, result) è lo standard nelle API di Node.js (fs.readFile, dns.lookup e molte altre).

Callback Hell: La Piramide del Doom

Le callback funzionano bene per una singola operazione. Il problema inizia quando un passo asincrono dipende dal risultato del precedente. Ogni passo si annida all'interno dell'ultimo e l'indentazione avanza verso destra — la cosiddetta piramide del doom:

javascript— editable

Con due passi è ancora leggibile. Aggiungerne un terzo e un quarto — ripetendo il controllo if (err) in ogni livello — rende il codice difficile da seguire, difficile da gestire in termini di errori e difficile da modificare. Questo è il callback hell, ed è il motivo principale per cui sono state introdotte le Promises.

Buone Pratiche per l'Uso delle Callback

Sebbene le callback siano potenti, usarle eccessivamente o in modo improprio può portare al "callback hell", dove il codice diventa troppo annidato ed è difficile da leggere e mantenere. Ecco alcune buone pratiche per mantenere il codice pulito:

  1. Modularizza il Codice: Suddividi le funzioni callback in funzioni più piccole e riutilizzabili. Questo approccio non solo migliora la leggibilità, ma facilita anche la manutenzione del codice.
  2. Gestisci gli Errori in Modo Elegante: Gestisci sempre gli errori nelle tue callback. Questa pratica previene crash e comportamenti indesiderati negli ambienti di produzione.
  3. Evita l'Annidamento Profondo: Cerca di appiattire le strutture di callback il più possibile. Strumenti come async/await o Promises possono aiutare a gestire le operazioni asincrone in modo più pulito.
  4. Attenzione alle Closure nei Loop: Quando si definiscono callback all'interno di loop, usa let o const per le variabili del loop per prevenire bug legati alle closure, dove tutte le callback catturano il valore finale del loop.

Andare Oltre le Callback: Promises e Async/Await

Sebbene le callback siano una parte fondamentale di JavaScript, il JavaScript moderno offre modi più astratti per gestire il codice asincrono, come Promises e async/await.

Usare le Promises

Una Promise rappresenta un valore che potrebbe essere disponibile ora, in futuro, o mai. Invece dell'annidamento, i passi dipendenti vengono concatenati uno dopo l'altro, il che appiattisce la piramide e centralizza la gestione degli errori in un unico .catch. Inizia con JavaScript: Promises, poi scopri come i passi si collegano in JavaScript: Promises Chaining.

Se hai una vecchia funzione basata su callback (come gli esempi divide o getUser sopra), puoi racchiuderla in modo che restituisca una Promise — una tecnica chiamata promisification. Consulta JavaScript: Promisification.

Async/Await: Un Approccio Più Pulito

La sintassi async/await consente di scrivere codice asincrono che si legge come codice sincrono. È costruita sopra le Promises ed è più intuitiva rispetto ai tradizionali schemi con callback. Leggi JavaScript: Async/Await per scoprire come puoi usare async/await al posto delle callback.

Conclusione

Comprendere e utilizzare efficacemente le callback è fondamentale per gli sviluppatori JavaScript. Seguendo le buone pratiche e usando le funzionalità moderne come Promises e async/await, puoi scrivere codice più pulito e manutenibile. Padroneggia questi concetti per migliorare le tue competenze di programmazione JavaScript e creare applicazioni più efficienti.

Pratica

Pratica
Cos'è una funzione callback in JavaScript e quando viene eseguita?
Cos'è una funzione callback in JavaScript e quando viene eseguita?
Was this page helpful?