【问题标题】:Passing variable in parent scope to callback function将父范围内的变量传递给回调函数
【发布时间】:2014-12-05 12:27:23
【问题描述】:

这更像是一个 JavaScript 闭包问题,而不是 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;
};

【问题讨论】:

    标签: javascript ajax closures firebase


    【解决方案1】:

    回调可以很好地识别/修改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 注册了一个侦听器,该侦听器将为添加到 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
    }
    

    【讨论】:

    • 感谢您的明确答复!最喜欢您的答案,但由于缺少徽章积分(提示)而无法投票。
    • 鉴于您提出了这个问题,您应该能够通过单击左侧的复选标记接受我的回答。见meta.stackexchange.com/questions/5234/…
    • 感谢弗兰克的回答 - 它对我正在构建的游戏有所帮助。
    【解决方案2】:

    child_added 事件不会立即执行,因此不是同步的,您不能依赖它在函数结束时的日志调用之前执行。

    程序是:

    • 定义 myArr
    • 实例化 Firebase
    • 为 child_added 分配事件处理程序
    • 记录 myArr 的值
    • 返回 myArr - 函数结束
    • 现在,在此之后的某个时间点,child_added 事件被触发,该事件将推送到您的数组,但是您可以看到,此时您的 show_fb() 函数已经完成执行。

    【讨论】:

      【解决方案3】:

      如果 Firebase 进行 ajax 调用(它可能会调用),那么回调函数(快照){..} 在 return 语句之后被调用。所以函数 show_fb 总是返回 []。

      例如:

      • 您执行以下语句:var x=show_fb();
        • show_fb 创建空数组
        • 函数创建 ajax 调用
        • 函数返回myArr(此时为空)
        • 变量 x 获得对 myArr 的引用(数组仍为空)
        • 回调被调用并向 x 插入新值(x 和 myArr 具有相同的实例)

      【讨论】:

        猜你喜欢
        • 2016-03-02
        • 2011-06-30
        • 1970-01-01
        • 1970-01-01
        • 2019-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-08
        相关资源
        最近更新 更多