2010-02-22 4 views
2

J'utilise des variables globales pour passer autour d'une réponse d'un appel AJAX:AJAX: Attente d'une réponse?

window.response = null; // most recent response from XMLHttpRequest 

// the callback function for XMLHttpRequest 
function userObjFromJSON() { 
    if (this.readyState == 4) { 
     var json = eval('(' + this.responseText + ')'); 
     window.response = json; 
    } 
    else { 
     indicateLoading(); 
    } 
} 

// loads the info for this username on the page 
function loadUsernameInfo(username) { 
    clearPage(); 
    getUserInfo(username); 
    var profile = window.response; // most recent json response (what if it hasn't come in yet?) 
    window.response = null; 
    if (profile) { 
     indicateLoaded(username); 
     fillInProfileInfo(profile); 

     getTweets(username); 
     var tweets = window.response; // most recent json response (what if it hasn't come in yet?) 
     if (tweets) { 
      fillInTweets(tweets, MAX_TWEETS); 
      var mentions = mentionedUsers(tweets, MAX_TWEETS); 
      fillInMentioned(mentions); 
     } 
     else { 
      indicateUnavailableTweets(); 
     } 
    } 
    else { 
     indicateInvalidUsername(username); 
    } 
} 

Le problème est que, au moment où la fonction de contrôleur veut commencer à remplir l'information, l'appel AJAX n'a ​​pas toujours retourné encore. (Si je le passe lentement dans un débogueur, ça fonctionne bien.) Que puis-je faire pour contourner cela?

J'ai essayé quelque chose comme ceci:

getUserInfo(username); 
while (window.response == null); // infinite loop here 
var profile = window.response; // most recent json response 

Mais ce juste fait mon navigateur ne répond pas.

J'hésite à appeler la fonction nécessaire à partir du rappel, parce que j'essaie d'implémenter model-view-controller. L'appel d'une fonction contrôleur/affichage à partir du modèle donne l'impression de rompre le motif.

Répondre

2

La meilleure pratique ici serait de placer le code que vous avez actuellement dans loadUsernameInfo dans le rappel pour l'appel AJAX lui-même, au lieu de s'appuyer sur la variable globale. De cette façon, lorsque votre réponse reviendra, le rappel qui s'exécute, au lieu de simplement définir votre variable window.response, ira de l'avant et mettra à jour votre interface utilisateur et effectuera toutes les autres tâches connexes.

Une autre façon de faire la même chose est juste pour appeler loadUsernameInfo de votre rappel existant, comme:

// the callback function for XMLHttpRequest 
function userObjFromJSON() { 
    if (this.readyState == 4) { 
     var profile = eval('(' + this.responseText + ')'); 
     loadUsernameInfo(username, profile); 
    } 
    else { 
     indicateLoading(); 
    } 
} 

Hope that helps!

0
function userObjFromJSON() { 
if (this.readyState == 4) { 
    var json = eval('(' + this.responseText + ')'); 
    window.response = json; 
// why dont you call needed function here ? 
} 
else { 
    indicateLoading(); 
} 

}

Pourquoi ne pas vous appeler toutes les fonctions nécessaires lorsque vous définissez window.response?

Dans le pire des cas, vous pouvez utiliser window.setTimeout pour attendre la réponse ajax mais le meilleur moyen est d'utiliser des événements.

0

Votre XMLHttpRequest doit utiliser l'événement onreadystatechange. par exemple:

var xmlHttp=new XMLHttpRequest(); 
xmlHttp.onreadystatechange=function(){ 
    if(xmlHttp.readyState!=4 || (xmlHttp.status!=200 && xmlHttp.status!=304))return; 
    callback(xmlHttp.responseText); 

} 

Où callback() est la fonction que vous voulez appeler. Un readyState de 4 signifie que le contenu a fini de charger. Et les deux entrées de statut doivent s'assurer que l'URL n'a pas donné d'erreur.

+0

J'essaie de faire model-view-controller, et mettre l'appel de fonction là-bas violerait cela. –