J'ai un peu de difficulté avec un tableau qui est (à l'extérieur d'un appel asynchrone) parfaitement bien défini, mais quand j'appelle ses indices dans une demande asynchrone (p. Ex. $ .getJSON), tous les indices du tableau sont indéfinis mais la longueur est Toujours le même. Voici mon code.
Le tableau auquel je me réfère est FriendsArray
Le tableau a l'indice correct pendant le deuxième appel "$ .getJSON", mais dans le rappel de cette fonction, tous ses indices deviennent indéfinis. Le réseau ne devrait-il pas conserver ses valeurs puisqu'il a été défini dans le cadre de la méthode?
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); } } });
}
Le problème est que la fonction de rappel arrive quelque temps plus tard lorsque la fonction ajax est terminée. À ce moment-là, l'index du tableau a avancé jusqu'à la fin de votre boucle for
(donc il pointe la fin du tableau) à une valeur indéfinie. Le tableau est toujours là, mais votre index a été modifié au moment où la fonction d'achèvement est appelée.
La technique habituellement utilisée pour obtenir l'indice dans le gestionnaire de succès est de le capturer dans une fermeture de fonction où il est capturé pour une utilisation dans la fonction d'achèvement.
Vous pouvez créer une fermeture qui capture la valeur de l'indice en remplaçant votre gestionnaire de succès par ceci:
(function(index) { return function(dataJSON2) { resultArray = dataJSON2['data']; resultJSON += friendArray[index] + ":" + resultArray.length + ","; //alert(resultJSON); } }) (i);
Cette fonction externe exécute et crée une fermeture qui saisit la valeur de i et la rend exclusivement disponible pour le gestionnaire de réussite. Lorsqu'il s'exécute automatiquement, il renvoie votre gestionnaire de succès qui est ainsi passé à la fonction getJSON à appeler plus tard. Mais, lorsqu'on l'appelle plus tard, la valeur de i
dont vous avez besoin est disponible pour le gestionnaire de succès via l'argument dans la fonction d'auto-exécution.
Voici une autre façon de penser aux fermetures utilisées avec les rappels.
Voici un exemple de ceci:
function cycleOnOff(sel, cnt, delay) { var obj = $(sel); function next() { if (cnt-- > 0) { obj.toggle(); setTimeout(next, delay); } } next(); }
Dans ce cas, la fonction next()
est un rappel pour setTimeout()
, mais cette fonction a un accès complet aux variables dans sa portée parentale: sel
, cnt
, delay
et obj
.