簡體   English   中英

將父作用域中的變量傳遞給回調函數

[英]Passing variable in parent scope to callback function

這更像是一個JavaScript Closure問題而不是Firebase問題。 在以下代碼中,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;
};

回調是完全myArr地識別/修改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注冊了一個監聽child_added ,該監聽器child_added添加到您的Firebase的每個帖子調用on_post_added
  2. 這將導致對服務器的調用,這可能需要很長時間才能返回
  3. 同時你的JavaScript代碼繼續......
  4. 記錄此階段仍為空的數組
  5. 然后返回一個空數組
  6. 現在,在某個時刻,服務器返回新值,並調用您的回調
  7. 這意味着我們可以毫無問題地將它添加到數組中
  8. 將其記錄到控制台會顯示預期值

像這樣處理異步代碼/回調需要一些人習慣,但對於使用Firebase或任何其他類似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
}

child_added事件不會立即執行,因此不是同步的,並且在函數結束時的日志調用之前,您不能依賴它來執行。

程序是:

  • 定義myArr
  • 實例化Firebase
  • 為child_added分配事件處理程序
  • 記錄myArr的值
  • 返回myArr - 函數結束
  • 現在在此之后的某個時刻,會觸發child_added事件,該事件將推送到您的數組,但正如您所看到的,您的show_fb()函數已經完成了此點的執行。

如果Firebase進行ajax調用(可能確實如此),則在return語句之后調用回調函數(快照){..}。 所以函數show_fb總是返回[]。

例如:

  • 執行以下語句:var x = show_fb();
    • show_fb創建空數組
    • function創建ajax調用
    • function返回myArr(此時為空)
    • 變量x引用myArr(數組仍為空)
    • 調用callback並將新值插入x(x和myArr具有相同的實例)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM