No, le chiamate di funzione ricorsive non causano perdite di memoria in Javascript.
L'unica memoria utilizzata da una chiamata di funzione è un po 'di spazio di stack (quindi l'interprete sa dove andare quando ritorna la funzione) e qualsiasi memoria viene utilizzata dall'oggetto scope della funzione (ad esempio le variabili locali). Quella memoria dello stack viene completata restituita al sistema quando ritorna la chiamata alla funzione. Non perde.
In JavaScript, con callback asincroni, la funzione di inizializzazione è già stata restituita e quindi lo stack è stato cancellato molto prima che il callback asincrono sia stato chiamato in modo che non ci sia accumulo dello stack.
Ci sarà un oggetto scope della funzione in memoria fino a quando il callback non viene eseguito e ciò è importante ed è necessario per consentire al callback inline di accedere alle variabili dichiarate nell'ambito genitore. Non appena il callback è terminato (non più raggiungibile), tale oggetto sarà raccolto. A meno che non si stia facendo qualcosa di insolito come stringhe giganti allocate o buffer in tale ambito temporaneo, l'utilizzo della memoria di tale ambito non dovrebbe costituire un problema.
Come per il recupero di molti messaggi da una chiamata di funzione iniziale e chiamate ripetute della stessa richiamata, tenere presente che la funzione genitore viene eseguita una sola volta e viene assegnato un solo oggetto di ambito, indipendentemente dal numero di richiamate richiamate quindi non c'è accumulo di memoria per ogni volta che viene richiamato il callback. Il callback stesso otterrà un nuovo ambito di funzione ogni volta che viene chiamato, ma poiché la richiamata stessa non attiva alcuna chiamata asincrona, quell'oggetto dell'ambito sarà temporaneo e sarà idoneo per la garbage collection non appena viene eseguita la richiamata con il suo lavoro e ritorni.
Se si concatenano/eseguono operazioni asincrone l'una nell'altra, gli oggetti di ambito aggiuntivi verranno conservati per la durata dell'operazione asincrona, ma questo è il modo in cui funziona JavaScript ed è ciò che offre le funzionalità di accesso all'ambito principale. In pratica, non è generalmente dimostrato che si tratti di un problema di memoria. Gli oggetti di ambito sono oggetti relativamente compatti (uno è creato per quasi tutte le chiamate di funzioni), come ho detto sopra, purché non si inseriscano buffer giganti o stringhe/array giganti in un ambito persistente, l'utilizzo della memoria di solito non è rilevante .
Anche tenere a mente che quando si chiama processMessage()
ancora una volta all'interno della callback asincrono che non è il tipo di ricorsione che si potrebbe pensare in generale perché la precedente chiamata di funzione per processMessage()
è già tornato e lo stack ha completamente slegato prima che l'evento asincrono abbia attivato il callback. Quindi, non ci sono accumuli di stack in questo caso. Questo perché le operazioni asincrone in Javascript passano tutte attraverso una coda di eventi. Quando un'operazione asincrona è pronta per attivare un'azione, inserisce un evento nella coda degli eventi di Javascript. Questo evento viene elaborato solo quando il thread corrente dell'operazione JS è terminato e completamente slegato. Solo allora l'interprete JS guarda nella coda degli eventi per vedere se c'è qualcos'altro da fare. Come tale, lo stack viene sempre completamente svolto prima dell'avvio della successiva operazione asincrona.
Per maggiori informazioni su come funziona e un certo numero di articoli di riferimento sulla coda degli eventi JS (che funziona allo stesso modo in node.js che lo fa nel browser), si veda questo articolo:
How does JavaScript handle AJAX responses in the background?
Questo è uno dei motivi per cui Joyent chiama node.js un "un modello I/O non bloccato e comandato da eventi" proprio sul node.js home page.
Questo non realmente * * ricorsiva, poiché ogni callback viene richiamato su una pila fresca quando l'evento asincrono attivazione avviene. In altre parole, la prima chiamata a 'processMessage()' sarà completata a lungo quando il prossimo avviene in risposta all'evento. – Pointy
si sarà in grado di vedere questo in ispettore chrome se si imposta una situazione in cui questo dovrebbe essere eseguito più volte. La mia ipotesi è che non ci dovrebbe essere un problema finché si completano i processi su ogni callback – BillPull