我在一个完全定义良好的数组(在异步调用之外)遇到一些困难但是当我在异步请求(例如$ .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);
}
}
});
}
答案 0 :(得分:4)
问题是回调函数在ajax函数完成后的某个时间发生。到那时,数组索引已经前进到for
循环的末尾(因此它指向数组的末尾)到一个未定义的值。数组仍然存在,但是在调用完成函数时您的索引已经更改。
通常用于将索引引入成功处理程序的技术是在函数闭包中捕获它,捕获它以在完成函数中使用。
您可以通过用以下代码替换成功处理程序来创建一个捕获索引值的闭包:
(function(index) {
return function(dataJSON2) {
resultArray = dataJSON2['data'];
resultJSON += friendArray[index] + ":" + resultArray.length + ",";
//alert(resultJSON);
}
}) (i);
此外部函数执行并创建一个闭包,该闭包捕获i的值并唯一使其可用于成功处理程序。当它自己执行时,它返回你的成功处理程序,因此传递给getJSON函数以便稍后调用。但是,当稍后调用它时,您需要的i
的值可通过自执行函数中的参数提供给成功处理程序。
这是考虑与回调一起使用的闭包的另一种方法。
以下是一个例子:
function cycleOnOff(sel, cnt, delay) {
var obj = $(sel);
function next() {
if (cnt-- > 0) {
obj.toggle();
setTimeout(next, delay);
}
}
next();
}
在这种情况下,函数next()
是对setTimeout()
的回调,但该函数可以完全访问其父作用域中的变量:sel
,cnt
, delay
和obj
。