2014-10-10 13 views
5

Jest to raczej pytanie o zamknięcie języka JavaScript niż pytanie Firebase. W poniższym kodzie wywołanie zwrotne Firebase nie rozpoznaje zmiennej myArr w zakresie nadrzędnym.Przekazywanie zmiennej w zakresie rodzica do funkcji zwrotnej

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

Odpowiedz

9

Funkcja zwrotna rozpoznaje/modyfikację myArr idealnie w porządku. Problem polega na tym, że kiedy twoje "nie działa" - oznaczane jako console.log(myArr), wywołanie zwrotne jeszcze się nie uruchomiło.

Zmieńmy trochę kodu:

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 
} 

Teraz to może być nieco łatwiej zobaczyć co się dzieje.

  1. zarejestrować detektor dla child_added że zadzwoni on_post_added dla każdego postu, który jest dodawany do Firebase
  2. Spowoduje to wywołanie do serwera, który może zająć znaczną ilość czasu, aby powrócić
  3. Tymczasem twój kod JavaScript jest kontynuowany i ...
  4. Rejestruje tablicę, która na tym etapie jest jeszcze pusty
  5. A potem ten sposób zwraca pustą tablicę
  6. Teraz w pewnym momencie serwer zwraca nową wartość (S) i swoją zwrotna jest wywoływana
  7. Czyli możemy dodać go do tablicy bez problemów
  8. I zalogowaniu się do konsoli pokazuje wartości oczekiwanych

kod obsługi asynchronicznego/wywołania zwrotne jak to trwa trochę przyzwyczaić, ale jest niezbędna do pracy z Firebase lub którykolwiek inną technologię podobną do AJAX lub opartą na zdarzeniach. Umieszczenie kodu wywołania zwrotnego w oddzielnej funkcji czasami ułatwia zrozumienie, co się dzieje.

W przypadku bazy Firebase może również pomóc w uświadomieniu sobie, że wydarzenie to jest z jakiegoś powodu nazywane child_added. Jest wywoływana za każdym razem, gdy dziecko jest dodawane do Bazy Firebase, a nie tylko wtedy, gdy po raz pierwszy rejestrujesz swoje oddzwanianie. Tak więc minut później, gdy jakiś inny klient doda dziecko, twoje wywołanie zwrotne nadal będzie uruchamiane, dodając nowe dziecko do myArr. Na tym etapie kod w krokach 4 i 5 powyżej zostanie wykonany i nie zostanie wykonany ponownie.

Rozwiązanie jest proste: umieścić wszystko, co chcesz robić po dziecko dodaje do swojej 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

Dzięki za jednoznaczną odpowiedź! Tak jak twoja odpowiedź najlepiej, ale nie jestem w stanie zagłosować z powodu braku punktów odznak (podpowiedź). –

+0

Biorąc pod uwagę, że zadałeś pytanie, powinieneś być w stanie ** zaakceptować ** moją odpowiedź, klikając znacznik wyboru po lewej stronie. Zobacz http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work –

+0

Dzięki za odpowiedź Frank - pomogło mi to w grze, którą buduję. – Nadjib

1

child_added zdarzenie nie jest wykonywana natychmiast, dlatego nie jest synchroniczna i nie można powoływać się na to, aby zostały wykonane, przed wywołaniem dziennika na koniec swojej funkcji.

Procedura jest:

  • Definiowanie myarr
  • Instantiate Firebase
  • Przypisywanie obsługi zdarzeń dla child_added
  • Zaloguj wartość myarr
  • Powrót myarr - koniec funkcji
  • teraz w pewnym momencie wydarzenie child_added jest uruchamiane, co powoduje przejście do twojej tablicy, ale jak widać, twoja zabawa show_fb() ction zakończył już wykonywanie tego punktu.
0

Jeśli Firebase wywołuje wywołanie ajax (prawdopodobnie tak jest), funkcja wywołania zwrotnego (snapshot) {..} jest wywoływana po instrukcji return. Zatem funkcja show_fb zawsze zwraca [].

na przykład:

  • wykonaniu tego komunikatu: var x = show_fb();
    • show_fb tworzy pustą tablicę
    • funkcja tworzy wywołanie ajax
    • zwraca myarr (jest pusta w tej chwili)
    • zmienna x dostaje odniesienie do myarr (tablica jest wciąż pusty)
    • zwrotna jest wywoływana i wstawia nową wartość x (xi myarr mają ten sam przypadek)
Powiązane problemy