简体   繁体   English

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

[英]Passing variable in parent scope to callback function

This is more of a JavaScript Closure question than a Firebase question. 这更像是一个JavaScript Closure问题而不是Firebase问题。 In the following code, the Firebase callback isn't recognizing the variable myArr in the parent scope. 在以下代码中,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;
};

The callback is recognizing/modifying myArr perfectly fine. 回调是完全myArr地识别/修改myArr The problem is that when your "doesn't work"-labeled console.log(myArr) executes, the callback hasn't fired yet. 问题是当你的“不工作”标记的console.log(myArr)执行时,回调还没有被触发。

Let's change your code a bit: 让我们稍微改变你的代码:

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
}

Now it might be a bit easier to see what's going on. 现在可能更容易看到发生了什么。

  1. You register a listener for child_added that will call on_post_added for every post that is added to your Firebase 您为child_added注册了一个监听child_added ,该监听器child_added添加到您的Firebase的每个帖子调用on_post_added
  2. This will result in a call to the server, which may take a significant amount of time to return 这将导致对服务器的调用,这可能需要很长时间才能返回
  3. Meanwhile your JavaScript code continues and... 同时你的JavaScript代码继续......
  4. Logs the array, which at this stage is still empty 记录此阶段仍为空的数组
  5. And then thus returns an empty array 然后返回一个空数组
  6. Now at some point the server returns the new value(s) and your callback is invoked 现在,在某个时刻,服务器返回新值,并调用您的回调
  7. Which means we can add it to the array without problems 这意味着我们可以毫无问题地将它添加到数组中
  8. And logging it to the console shows the expected values 将其记录到控制台会显示预期值

Handling asynchronous code/callbacks like this takes some getting used to, but is crucial to working with Firebase or any other AJAX-like or event driven technology. 像这样处理异步代码/回调需要一些人习惯,但对于使用Firebase或任何其他类似AJAX或事件驱动的技术至关重要。 Putting the callback's code into a separate function sometimes makes it a bit easier to see what's going on. 将回调代码放入一个单独的函数有时可以更容易地看到正在发生的事情。

In the case of Firebase it may also help to realize that the event is called child_added for a reason. 对于Firebase,它也可能有助于意识到事件被称为child_added有一个原因。 It is called whenever a child is added to the Firebase, not just when you first register your callback. 只要孩子被添加到Firebase,就会调用它,而不仅仅是在您第一次注册回调时。 So minutes later when some other client adds a child, your callback will still fire, adding a new child to myArr . 所以几分钟后,当其他一些客户端添加一个孩子时,你的回调仍然会触发,向myArr添加一个新的孩子。 At that stage the code in steps 4 and 5 above will long have executed and will not execute again. 在那个阶段,上面的步骤4和5中的代码将长期执行,并且不会再次执行。

The solution is simple: put anything that you want to do after a child is added into your callback: 解决方案很简单:在将子项添加到回调中之后放置您想要执行的任何操作:

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
}

The child_added event is not immediately executed, therefore is not synchronous and you can't rely on it to have executed, before the log call at the end of your function. child_added事件不会立即执行,因此不是同步的,并且在函数结束时的日志调用之前,您不能依赖它来执行。

The procedure is: 程序是:

  • Define myArr 定义myArr
  • Instantiate Firebase 实例化Firebase
  • Assign event handler for child_added 为child_added分配事件处理程序
  • Log the value of myArr 记录myArr的值
  • Return myArr - end of function 返回myArr - 函数结束
  • Now at some point after this, the child_added event is fired, which pushes to your array, but as you can see, your show_fb() function has already finished executing by this point. 现在在此之后的某个时刻,会触发child_added事件,该事件将推送到您的数组,但正如您所看到的,您的show_fb()函数已经完成了此点的执行。

If Firebase makes ajax call(it probably does), then callback function(snapshot){..} is called after return statement. 如果Firebase进行ajax调用(可能确实如此),则在return语句之后调用回调函数(快照){..}。 So function show_fb always returns []. 所以函数show_fb总是返回[]。

for instance: 例如:

  • You execute this statement: var x=show_fb(); 执行以下语句:var x = show_fb();
    • show_fb creates empty array show_fb创建空数组
    • function creates ajax call function创建ajax调用
    • function returns myArr (it is empty at this moment) function返回myArr(此时为空)
    • variable x gets reference to myArr (array is still empty) 变量x引用myArr(数组仍为空)
    • callback is called and inserts new value to x (x and myArr have same instance) 调用callback并将新值插入x(x和myArr具有相同的实例)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM