2014-10-10 114 views
5

這是一個比Firebase問題更多的JavaScript Closure問題。在以下代碼中,Firebase回調無法識別父作用域中的變量myArr。因此將父範圍中的變量傳遞給回調函數

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

回答

9

回調被識別/修改myArr非常好。問題是,當你的「不起作用」 - 標籤console.log(myArr)執行時,回調尚未開啓。

讓我們改變你的代碼位:

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 
} 

現在,它可能會更容易一點,看看發生了什麼事情。

  1. 您註冊child_added監聽器,將調用on_post_added對於被添加到您的火力地堡的每一個崗位
  2. 這將導致到服務器的呼叫,這可能需要很長時間顯著量返回
  3. 同時你的JavaScript代碼還在繼續...
  4. 日誌的陣列,在這個階段仍然是空的
  5. 然後因而在某些時候,服務器返回的新值(s)返回一個空數組
  6. 現在和你調用回調函數
  7. 這意味着我們可以把它添加到陣列中沒有問題
  8. 它記錄到控制檯顯示的預期值

處理異步代碼/像這樣的回調需要一些時間來適應,但關鍵的是要與火力地堡或任何工作其他類似AJAX或事件驅動的技術。將回調的代碼放入一個單獨的函數中,有時可以更容易地看到發生了什麼。

在Firebase的情況下,它也可能有助於認識到事件被稱爲child_added的原因。無論何時將孩子添加到Firebase,都會調用它,而不僅僅是在您首次註冊回調時。在幾分鐘後,當其他客戶添加一個孩子時,您的回調仍然會觸發,並將新的孩子添加到myArr。在那個階段上面的步驟4和5中的代碼將長時間執行並且不會再執行。

解決方法很簡單:把你想要做一個孩子加入到你的回調後,任何東西:

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

感謝明確的答案!像你最好的答案一樣,但由於缺乏徽章點(提示)而無法投票。 – 2014-10-10 13:38:17

+0

考慮到您提出的問題,您應該可以通過點擊左側的複選標記來接受**我的答案。見http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – 2014-10-10 15:00:37

+0

感謝您的答案弗蘭克 - 它只是幫助我在我正在建設的遊戲。 – Nadjib 2015-11-15 21:17:14

1

的child_added事件不會立即執行,是不是同步的,你不能依靠它來已執行,在你的函數結束日誌調用之前。

的程序是:

  • 定義myArr,該
  • 實例化火力地堡
  • 爲child_added
  • 分配事件處理程序日誌myArr,該
  • 返回myArr,該 - 功能end現在
  • 在這之後的某個時刻,child_added事件被觸發,這會推送到你的數組,但正如你所看到的,你的show_fb()有趣這一點已經完成執行。
0

如果Firebase進行ajax調用(可能會),那麼在return語句後調用回調函數(snapshot){..}。所以函數show_fb總是返回[]。

例如:

  • 執行這個語句:var X = show_fb();
    • show_fb創建空數組
    • 函數創建AJAX調用
    • 函數返回myArr,該(它是空的,在這一刻)
    • 變量x獲取參照myArr,該(陣列仍然是空的)
    • 回調被調用並插入新值X(X和myArr,該具有相同的實例)
相關問題