2014-10-10 7 views
5

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.Passaggio della variabile nell'ambito genitore alla funzione di callback

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; 
}; 

risposta

9

La richiamata è riconoscere/modifica myArr perfettamente bene. Il problema è che quando il tuo "non funziona", con l'etichetta console.log(myArr), viene eseguito, la richiamata non è ancora stata attivata.

Cambiamo il codice un po ':

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 per vedere cosa sta succedendo.

  1. si registra un listener per child_added che chiamerà on_post_added per ogni post che viene aggiunto al tuo Firebase
  2. Questo si tradurrà in una chiamata al server, che può richiedere una notevole quantità di tempo per tornare
  3. Nel frattempo il tuo codice JavaScript continua e ...
  4. registra la matrice, che in questa fase è ancora vuota
  5. E poi torna così un array vuoto
  6. Ora, a un certo punto il server restituisce il nuovo valore (s) e il callback viene richiamato
  7. Il che significa possiamo aggiungere alla matrice senza problemi
  8. e la registrazione alla console mostra i valori attesi

Manipolazione codice asincrono/callback come questo richiede un po 'per abituarsi, ma è fondamentale per lavorare con Firebase o qualsiasialtra 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: mettere tutto ciò che si vuole fare dopo che un bambino viene aggiunto il 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 
} 
+0

Grazie per la risposta chiara! Come la tua risposta, ma non posso votare per mancanza di punti badge (suggerimento). –

+0

Dato che hai posto la domanda, dovresti essere in grado di ** accettare ** la mia risposta facendo clic sul segno di spunta a sinistra di essa. Vedi http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work –

+0

Grazie per la risposta Frank - mi ha appena aiutato nel gioco che sto costruendo. – Nadjib

1

L'evento child_added non è immediatamente eseguita, quindi non è sincrona e non si può fare affidamento su di esso per aver eseguito, prima della chiamata di registro al termine della funzione.

La procedura è:

  • Definire myArr
  • un'istanza di Firebase
  • gestore di eventi Assegna per child_added
  • Accedere il valore di myArr
  • ritorno myArr - fine della funzione
  • Ora ad un certo punto dopo questo, viene attivato l'evento child_added, che spinge al tuo array, ma come puoi vedere, il tuo divertimento show_fb() ction ha già completato l'esecuzione a questo punto.
0

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:

  • Si esegue questa dichiarazione: var x = show_fb();
    • show_fb crea matrice vuota
    • funzione crea chiamata ajax
    • funzione restituisce myArr (è vuoto in questo momento)
    • variabile x viene riferimento myArr (array è ancora vuoto)
    • callback viene chiamato e inserisce il nuovo valore di x (x e myArr hanno stessa istanza)
Problemi correlati