Les variables définies pendant la fonction $ .getJSON sont accessibles uniquement dans la fonction

Cela peut être plus une question de portée. J'essaie de définir un objet JSON dans une fonction $ .getJSON, mais je dois pouvoir utiliser cet objet en dehors du rappel.

var jsonIssues = {}; // declare json variable $.getJSON("url", function(data) { jsonIssues = data.Issues; }); // jsonIssues not accessible here 

Une question semblable à celle-ci a été posée dans un autre post, et le consensus était que tout ce que je dois faire avec les objets JSON doit être fait dans la fonction de rappel et ne peut être consulté ailleurs. Est-ce qu'il n'y a vraiment aucun moyen de continuer à accéder / manipuler cet objet JSON en dehors du rappel $ .getJSON? Qu'en est-il de retourner la variable ou de définir une version globale?

J'apprécierais toute aide. Cela ne semble pas correct …

METTRE À JOUR:

Essayé de définir le paramètre $ .ajax () async sur false, et en cours d'exécution avec le même code, sans chance. Le code que j'ai essayé est ci-dessous:

 var jsonIssues = {}; // declare json variable $.ajax({ async: false }); $.getJSON("url", function(data) { jsonIssues = data.Issues; }); // jsonIssues still not accessible here 

De plus, j'ai eu quelques réponses selon lesquelles une variable globale devrait fonctionner correctement. Je devrais préciser que tout ce code est dans $(document).ready(function() { . Pour définir une variable globale, devrais-je la déclarer avant le document. En tant que tel:

 var jsonIssues = {}; $(document).ready(function() { var jsonIssues = {}; // declare json variable $.getJSON("url", function(data) { jsonIssues = data.Issues; }); // now accessible? } 

J'avais l'impression qu'une variable déclarée dans document.ready devrait être "globalement" accessible et modifiable dans n'importe quelle partie de document.ready, y compris des sous-fonctions comme la fonction de rappel $ .getJSON. Je devrais peut-être lire sur le domaine de la variable javascript, mais il ne semble pas facile de réaliser ce que je vais faire. Merci pour toutes les réponses.

MISE À JOUR # 2: Par commentaires donnés aux réponses ci-dessous, j'ai utilisé $ .ajax au lieu de .getJSON, et j'ai atteint les résultats que je voulais. Le code est ci-dessous:

 var jsonIssues = {}; $.ajax({ url: "url", async: false, dataType: 'json', success: function(data) { jsonIssues = data.Issues; } }); // jsonIssues accessible here -- good!! 

Les commentaires de couple de suivi à mes réponses (et je les apprécie tous). Mon but est de charger un objet JSON initialement avec une liste de problèmes que l'utilisateur peut ensuite supprimer et sauvegarder. Mais cela se fait via des interactions ultérieures sur la page, et je ne peux pas prévoir ce que l'utilisateur voudra faire avec l'objet JSON dans le rappel. D'où la nécessité de le rendre accessible une fois le rappel terminé. Est-ce que quelqu'un voit un défaut dans ma logique ici? Sérieusement, parce qu'il peut y avoir quelque chose que je ne vois pas …

En outre, je lisais la documentation jjuery .ajax (), et il dit que le réglage de l'asynch sur le faux "Charge les données de manière synchrone. Bloque le navigateur pendant que les requêtes sont actives. Il est préférable de bloquer l'interaction de l'utilisateur par d'autres moyens lorsque la synchronisation est nécessaire . "

Est-ce que quelqu'un a une idée de comment je bloquerais l'interaction de l'utilisateur alors que cela se passe? Pourquoi est-ce une préoccupation? Merci encore pour toutes les réponses.

$.getJSON est asynchrone. C'est-à-dire le code après l'exécution de l'appel tandis que $.getJSON récupère et analyse les données et appelle votre rappel.

Donc, compte tenu de ceci:

 a(); $.getJSON("url", function() { b(); }); c(); 

L'ordre des appels de a , b et c peut être soit abc (ce que vous voulez, dans ce cas) ou acb (plus susceptibles de se produire réellement).

La solution?

Demandes de XHR synchrones

Faire la demande synchrone au lieu d'être asynchrone:

 a(); $.ajax({ async: false, url: "url", success: function() { b(); } }); c(); 

Code de restructuration

Déplacez l'appel vers c après l'appel vers b :

 a(); $.getJSON("url", function() { b(); c(); }); 

Rappelez-vous que lorsque vous fournissez une fonction de rappel, le but est de différer l'exécution de ce rappel jusqu'à plus tard et de continuer immédiatement l'exécution de ce qui suit. Ceci est nécessaire en raison du modèle d'exécution à simple thread de JavaScript dans le navigateur. Le forçage de l'exécution synchrone est possible, mais il accroche le navigateur pendant toute la durée de l'opération. Dans le cas de quelque chose comme $ .getJSON, c'est un temps prohibitif pour le navigateur arrêter de répondre.

En d'autres termes, vous essayez de trouver un moyen d'utiliser ce paradigme procédural:

 var foo = {}; $.getJSON("url", function(data) { foo = data.property; }); // Use foo here. 

Lorsque vous devez refactoriser votre code afin qu'il coule plus comme ceci:

 $.getJSON("url", function(data) { // Do something with data.property here. }); 

"Faire quelque chose" pourrait être un appel à une autre fonction si vous voulez garder la fonction de rappel simple. La partie importante est que vous attendez jusqu'à ce que $ .getJSON soit terminé avant d'exécuter le code.

Vous pourriez même utiliser des événements personnalisés afin que le code que vous avez placé après $ .getJSON s'abonne à un événement ProblemReceived et que vous soulevez cet événement dans le rappel $ .getJSON:

 $(document).ready(function() { $(document).bind('IssuesReceived', IssuesReceived) $.getJSON("url", function(data) { $(document).trigger('IssuesReceived', data); }); }); function IssuesReceived(evt, data) { // Do something with data here. } 

Mettre à jour:

Ou, vous pouvez stocker les données à l'échelle mondiale et utiliser simplement l'événement personnalisé pour signaler que les données ont été reçues et que la variable globale a été mise à jour.

 $(document).ready(function() { $(document).bind('IssuesReceived', IssuesReceived) $.getJSON("url", function(data) { // I prefer the window.data syntax so that it's obvious // that the variable is global. window.data = data; $(document).trigger('IssuesReceived'); }); }); function IssuesReceived(evt) { // Do something with window.data here. // (eg create the drag 'n drop interface) } // Wired up as the "drop" callback handler on // your drag 'n drop UI. function OnDrop(evt) { // Modify window.data accordingly. } // Maybe wired up as the click handler for a // "Save changes" button. function SaveChanges() { $.post("SaveUrl", window.data); } 

Mise à jour 2:

En réponse à cela:

Est-ce que quelqu'un a une idée de comment je bloquerais l'interaction de l'utilisateur alors que cela se passe? Pourquoi est-ce une préoccupation? Merci encore pour toutes les réponses.

La raison pour laquelle vous devriez éviter de bloquer le navigateur avec des appels AJAX synchrones, c'est qu'un thread JavaScript bloqué bloque tout le reste du navigateur , y compris d'autres onglets et même d'autres fenêtres. Cela signifie pas de défilement, pas de navigation, pas de rien. À toutes fins utiles, il semble que le navigateur s'est écrasé. Comme vous pouvez l'imaginer, une page qui se comporte de cette façon est une nuisance importante pour ses utilisateurs.

Peut-être ce travail, me travaille … 🙂

 $variable= new array(); $.getJSON("url", function(data){ asignVariable(data); } function asignVariable(data){ $variable = data; } console.log($variable); 

J'espère que ça vous aidera … 🙂

"Mais cela se fait via des interactions ultérieures sur la page, et je ne peux pas prévoir ce que l'utilisateur voudra faire avec l'objet JSON dans le rappel".

Le rappel est l'occasion de configurer l'écran pour l'interaction de l'utilisateur avec les données.

Vous pouvez créer ou révéler du HTML pour l'utilisateur et configurer plus de rappels.

La plupart du temps, aucun de vos codes ne fonctionnera. La programmation d'une page Ajax consiste à penser à quel événement peut se produire quand.

Il y a une raison pour laquelle c'est "Ajax" et non "Sjax". Il y a une raison pour laquelle il est pénible de passer de l'asynchronisation à la synchronisation. Il est prévu que vous allez faire la page asynchrone.

La programmation événementielle peut être frustrante au début.

J'ai eu des algorithmes financiers intensifs en calcul dans JS. Même alors, c'est la même chose – vous l'avez divisé en petites parties, et les événements sont des délais.

L'animation en JavaScript est également organisée. En fait, le navigateur ne montrera même pas le mouvement à moins que votre script ne cesse de contrôler à plusieurs reprises.

Vous pouvez aborder cela avec des promesses:

 var jsonPromise = $.getJSON("url") jsonPromise.done(function(data) { // success // do stuff with data }); jsonPromise.fail(function(reason) { // it failed... handle it }); // other stuff .... jsonPromise.then(function(data) { // do moar stuff with data // will perhaps fire instantly, since the deferred may already be resolved. }); 

Il est très simple et une façon viable de faire ressortir le code asynchique est plus impératif.

Vous rencontrez uniquement des problèmes de portée.

Réponse courte:

 window.jsonIssues = {}; // or tack on to some other accessible var $.getJSON("url", function(data) { window.jsonIssues = data.Issues; }); // see results here alert(window.jsonIssues); 

Réponses longues:

Problème de portée sur Javascript Javascript clôturant problème