Passare la variabile nell’ambito genitore alla funzione di callback

Questa è più una domanda di chiusura JavaScript che una domanda Firebase. Nel codice seguente, il callback di Firebase non riconosce la variabile myArr nell’ambito genitore.

function show_fb() { var myArr = []; var firebase = new Firebase('https://scorching-fire-6816.firebaseio.com/'); firebase.on('child_added', function(snapshot) { var newPost = snapshot.val(); myArr.push(newPost.user); console.log(myArr); // works }); console.log(myArr); // doesn't work. myArr in the firebase.on callback is // not altering myArr return myArr; }; 

Il callback riconosce / modifica myArr perfettamente bene. Il problema è che quando il tuo “non funziona”, chiamato console.log(myArr) , viene eseguito, la richiamata non è ancora stata console.log(myArr) .

Cambiamo un po ‘il tuo codice:

 var myArr = []; function show_fb() { var firebase = new Firebase('https://scorching-fire-6816.firebaseio.com/'); firebase.on('child_added', on_post_added); // steps 1-3 console.log(myArr); // step 4 return myArr; // step 5 }; function on_post_added(snapshot) { // step 6 var newPost = snapshot.val(); myArr.push(newPost.user); // step 7 console.log(myArr); // step 8 } 

Ora potrebbe essere un po ‘più facile vedere cosa sta succedendo.

  1. Registri un ascoltatore per child_added che chiamerà on_post_added per ogni post che viene aggiunto al tuo Firebase
  2. Ciò comporterà una chiamata al server, che potrebbe richiedere molto tempo per la restituzione
  3. Nel frattempo il tuo codice JavaScript continua e …
  4. Registra l’array, che a questo punto è ancora vuoto
  5. E quindi restituisce una matrice vuota
  6. Ora a un certo punto il server restituisce il nuovo valore (s) e viene richiamata la richiamata
  7. Il che significa che possiamo aggiungerlo all’array senza problemi
  8. E registrarlo alla console mostra i valori attesi

Gestire codice asincrono / callback come questo richiede un po ‘di tempo per abituarsi, ma è fondamentale per lavorare con Firebase o qualsiasi altra tecnologia basata su AJAX o evento. Mettere il codice del callback in una funzione separata a volte rende un po ‘più facile vedere cosa sta succedendo.

Nel caso di Firebase può anche aiutare a capire che l’evento è chiamato child_added per un motivo. Viene chiamato ogni volta che un bambino viene aggiunto al Firebase, non solo quando si registra per la prima volta il callback. Così pochi minuti dopo, quando un altro client aggiunge un figlio, il tuo callback continuerà a sparare, aggiungendo un nuovo figlio a myArr . A quel punto il codice nei passaggi 4 e 5 sopra sarà eseguito a lungo e non verrà eseguito nuovamente.

La soluzione è semplice: metti tutto ciò che vuoi fare dopo che un bambino è stato aggiunto al tuo callback:

 var myArr = []; function show_fb() { var firebase = new Firebase('https://scorching-fire-6816.firebaseio.com/'); firebase.on('child_added', on_post_added); }; function on_post_added(snapshot) { var newPost = snapshot.val(); myArr.push(newPost.user); console.log(myArr); // do whatever else you need to do for a new post } 

L’evento child_added non viene eseguito immediatamente, quindi non è sincrono e non è ansible fare affidamento su di esso per essere eseguito, prima della chiamata di registro alla fine della funzione.

La procedura è:

  • Definisci myArr
  • Instantiate Firebase
  • Assegna gestore eventi per child_added
  • Registra il valore di myArr
  • Restituisce myArr – fine della funzione
  • Ora, a un certo punto, viene generato l’evento child_added, che invia all’array, ma come puoi vedere, la funzione show_fb () ha già terminato di essere eseguita da questo punto.

Se Firebase effettua una chiamata ajax (probabilmente lo fa), la funzione di callback (snapshot) {..} viene chiamata dopo l’istruzione return. Quindi la funzione show_fb restituisce sempre [].

per esempio:

  • Esegui questa dichiarazione: var x = show_fb ();
    • show_fb crea una matrice vuota
    • la funzione crea una chiamata Ajax
    • la funzione restituisce myArr (è vuota in questo momento)
    • variabile x ottiene riferimento a myArr (l’array è ancora vuoto)
    • il callback viene chiamato e inserisce un nuovo valore in x (x e myArr hanno la stessa istanza)