2014-10-10 18 views
5

Đây là câu hỏi về JavaScript đóng cửa nhiều hơn câu hỏi Firebase. Trong đoạn mã sau, gọi lại Firebase không nhận ra myArr biến trong phạm vi cha mẹ.Chuyển biến trong phạm vi gốc thành hàm gọi lại

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

Trả lời

9

Các callback được công nhận/sửa đổi myArr hoàn toàn ổn. Vấn đề là khi "không hoạt động" được gắn nhãn console.log(myArr) thực thi, cuộc gọi lại chưa được kích hoạt.

Hãy thay đổi mã của bạn một chút:

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 
} 

Bây giờ nó có thể là một chút dễ dàng hơn để xem những gì đang xảy ra.

  1. Bạn đăng ký một người biết lắng nghe cho child_added rằng sẽ gọi on_post_added cho mỗi bài đó sẽ được thêm vào căn cứ hỏa lực của bạn
  2. này sẽ dẫn đến một cuộc gọi đến máy chủ, có thể mất một số lượng đáng kể thời gian để trở lại
  3. Khi đó mã JavaScript của bạn tiếp tục và ...
  4. Logs mảng, mà ở giai đoạn này vẫn còn trống
  5. Và sau đó do đó trả về một mảng trống
  6. Bây giờ tại một số điểm máy chủ trả về giá trị mới (s) và gọi lại của bạn được gọi
  7. Có nghĩa chúng ta có thể thêm nó vào mảng không có vấn đề
  8. Và đăng nhập nó vào giao diện điều khiển cho thấy các giá trị dự kiến ​​

Xử lý mã không đồng bộ/callbacks như thế này phải mất một số để làm quen, nhưng là rất quan trọng để làm việc với các căn cứ hỏa lực hay bất kỳ công nghệ điều khiển sự kiện hoặc AJAX khác. Việc đặt mã của hàm gọi lại vào một hàm riêng biệt đôi khi làm cho nó dễ dàng hơn một chút để xem điều gì đang xảy ra.

Trong trường hợp Firebase, cũng có thể giúp nhận ra rằng sự kiện được gọi là child_added vì một lý do. Nó được gọi bất cứ khi nào một đứa trẻ được thêm vào Firebase, không chỉ khi bạn lần đầu tiên đăng ký gọi lại của bạn. Vì vậy, vài phút sau khi một số khách hàng khác thêm một đứa trẻ, cuộc gọi lại của bạn sẽ vẫn kích hoạt, thêm một đứa trẻ mới vào myArr. Ở giai đoạn đó, mã trong các bước 4 và 5 ở trên sẽ được thực thi và sẽ không thực hiện lại.

Giải pháp là đơn giản: đặt bất cứ điều gì mà bạn muốn làm sau khi một đứa trẻ được bổ sung vào callback của bạn:

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

Cảm ơn cho câu trả lời rõ ràng! Giống như câu trả lời của bạn tốt nhất nhưng tôi không thể bỏ phiếu vì thiếu điểm huy hiệu (gợi ý). –

+0

Vì bạn đã đặt câu hỏi, bạn sẽ có thể ** chấp nhận ** câu trả lời của tôi bằng cách nhấp vào dấu kiểm ở bên trái của nó. Xem http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work –

+0

Cảm ơn câu trả lời Frank - nó đã giúp tôi trong trò chơi tôi đang xây dựng. – Nadjib

1

Sự kiện child_added không được thực thi ngay lập tức, do đó không đồng bộ và bạn không thể dựa vào nó để thực hiện trước khi cuộc gọi nhật ký kết thúc chức năng của bạn.

Thủ tục là:

  • Xác định myArr
  • nhanh chóng căn cứ hỏa lực
  • Gán xử lý sự kiện cho child_added
  • Đăng nhập giá trị của myArr
  • Return myArr - cuối chức năng
  • Bây giờ tại một số điểm sau này, sự kiện child_added được kích hoạt, nó sẽ đẩy vào mảng của bạn, nhưng như bạn có thể thấy, show_fb() của bạn vui vẻ ction đã hoàn tất việc thực thi trước thời điểm này.
0

Nếu Firebase thực hiện cuộc gọi ajax (có thể có), thì chức năng gọi lại (ảnh chụp nhanh) {..} được gọi sau câu lệnh trả về. Vì vậy hàm show_fb luôn trả về [].

ví dụ:

  • Bạn thực hiện tuyên bố này: var x = show_fb();
    • show_fb tạo mảng trống
    • chức năng tạo cuộc gọi ajax
    • hàm trả myArr (nó là trống rỗng tại thời điểm này)
    • biến x được tham chiếu đến myArr (mảng vẫn còn trống)
    • callback được gọi là và chèn giá trị mới cho x (x và myArr có cùng dụ)
Các vấn đề liên quan