将父作用域中的变量传递给回调函数

Joh*_*son 5 javascript ajax closures firebase

这更像是一个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;
};
Run Code Online (Sandbox Code Playgroud)

Fra*_*len 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
}
Run Code Online (Sandbox Code Playgroud)

现在可能更容易看到发生了什么.

  1. 您注册了一个监听器,用于child_added调用on_post_added添加到Firebase的每个帖子
  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
}
Run Code Online (Sandbox Code Playgroud)