2014-10-10 143 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,该具有相同的实例)