javascript - 异步请求后数组中 undefined index

标签 javascript jquery ajax json asynchronous

我在使用一个(在异步调用之外)定义良好的数组时遇到了一些困难,但是当我在异步请求(例如 $.getJSON)中调用它的索引时,数组的所有索引都未定义但是长度 还是一样的。这是我的代码。

我指的数组是friendsArray

该数组在第二次“$.getJSON”调用期间具有正确的索引,但在该函数的回调中,其所有索引都变为未定义。数组不应该保留它的值,因为它是在方法的范围内定义的吗?

if (response.status === 'connected') { 
var accessToken = $.trim(response.authResponse.accessToken);
var hashArray = [];
var friendArray = [];
document.getElementById("statusCheck").innerHTML = accessToken;
$.getJSON('https://graph.facebook.com/me/friends?access_token=' + accessToken, 
  function(dataJSON){
    hashArray = dataJSON['data'];
    for (var i = 0; i < hashArray.length; i++){
        friendArray.push(hashArray[i]["id"]);
    }
    var resultJSON = "{";
    var resultArray = [];

    for (var i = 0; i < friendArray.length; i++){
        $.getJSON('https://graph.facebook.com/me/mutualfriends/' + 
                  friendArray[i] + "?access_token=" + accessToken, 
            function(dataJSON2){
                resultArray = dataJSON2['data'];
                resultJSON += friendArray[i] + ":" + resultArray.length + ",";
                //alert(resultJSON);
            })
        if (i == friendArray.length - 1){
            postArrayPopulation(resultJSON);
        }
    }

});         

最佳答案

问题是当 ajax 函数完成后,回调函数发生了一段时间。到那时,数组索引已经前进到 for 循环的末尾(因此它指向数组的末尾)到一个未定义的值。该数组仍然存在,但在调用完成函数时您的索引已更改。

通常用于将索引放入成功处理程序的技术是在函数闭包中捕获它,在函数闭包中捕获它以用于完成函数。

您可以通过将成功处理程序替换为以下代码来创建一个捕获索引值的闭包:

(function(index) {
    return function(dataJSON2) {
        resultArray = dataJSON2['data'];
        resultJSON += friendArray[index] + ":" + resultArray.length + ",";
        //alert(resultJSON);
    }
}) (i);

此外部函数执行并创建一个闭包,该闭包捕获 i 的值并唯一地使其可用于成功处理程序。当它自行执行时,它会返回您的成功处理程序,从而将其传递给 getJSON 函数以供稍后调用。但是,当稍后调用它时,您需要的 i 的值可通过自执行函数中的参数提供给成功处理程序。

这是考虑与回调一起使用的闭包的另一种方式。

  1. 任何函数在声明时都可以访问作用域内的所有变量,甚至是父作用域中更高级别的变量,即使该函数稍后作为回调调用也是如此。这实际上是许多其他语言所没有的 javascript 的一个巨大特性。
  2. 因此,如果我们希望一个变量在稍后执行回调时可用于回调函数,我们只需要以某种方式将该变量放入该回调函数的范围内。

举个例子:

function cycleOnOff(sel, cnt, delay) {
    var obj = $(sel);

    function next() {
        if (cnt-- > 0) {
            obj.toggle();
            setTimeout(next, delay);
        }
    }
    next();
}

在这种情况下,函数 next() 是对 setTimeout() 的回调,但该函数可以完全访问其父范围内的变量:selcntdelayobj

  1. 如果变量在最初设置回调和回调被调用之间没有变化,那就很容易了。您可以只使用匿名函数声明,并且在稍后调用回调时,在定义匿名函数时可用的所有更高范围变量仍然可用。
  2. 如果变量确实随着代码的继续执行而改变,并且您希望在稍后调用回调时将其现在可用的特定值设置为 - 这时候它会变得有点棘手。可以做的是创建一个将此变量传递给的函数,从而创建一个范围,其中该变量具有您想要的值并且不会随着其他代码的继续执行而改变。但是,因为我们想要的是回调函数,而不仅仅是函数调用,所以我们必须以一种半奇怪的方式将两者结合起来。我们进行函数调用并将所需的值传递给它。在该函数调用中,我们返回对回调函数的引用。这会适本地分配回调函数,但它将回调函数放入一个闭包中,该闭包捕获我们所需变量的值。更好的是,这个闭包对于回调的这个特定实例是唯一的,所以回调的每次使用都会有它自己的闭包,因此它有自己唯一的变量值。我们为您的特定问题创建的闭包/回调就是一个例子。

关于javascript - 异步请求后数组中 undefined index ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8623088/

相关文章:

JavaScript 未捕获类型错误 : showcreate1 is not a function

javascript - 无法使用 jquery/ajax/json 从 mysql 获取数据以选择框

javascript - 我如何使用 jquery 根据 url 中的关键字更改 css 类

javascript - 是否建议将 angularjs 用于基于大规模身份验证的应用程序?

javascript - 我如何仅使用 javascript 获取事件类的索引

javascript - 如何为 chrome 扩展制作开/关按钮/图标?

javascript - 如何避免多次发送表单

jquery - 为什么 jQuery 插件 Globalize 可以识别英语语言环境 (en-CA) 中的 9,999.99,但不能识别法语语言环境中的 9 999,99?

javascript - 如何用jquery创建动态复制按钮?

javascript - 如何更改方法返回的值(JavaScript OOP)