2009-10-04 8 views
0

Ce code ne fonctionne que si async est défini sur false, pourquoi?Demande asynchrone Javascript ne fonctionne pas

var contact = 
{ 
    XMLHttp : null, 
    XMLDoc : null, 
    TXTDoc : null, 

    getData : function(dataSource) 
    { 
     contact.XMLHttp = new XMLHttpRequest(); 
     contact.XMLHttp.open("GET", dataSource, false); 
     contact.XMLHttp.onreadystatechange = contact.storeData; 
     contact.XMLHttp.send(null); 
    }, 

    storeData : function() 
    { 
     if(contact.XMLHttp.readyState == 4 && contact.XMLHttp.status == 200) 
     { 
      contact.XMLDoc = contact.XMLHttp.responseXML; 
      contact.TXTDoc = contact.XMLHttp.responseText; 
     } 
    }, 

    displayData : function(elementID) 
    { 
     if(contact.TXTDoc != null) 
      document.getElementById(elementID).innerHTML = contact.TXTDoc; 
     else{ 
     document.getElementById(elementID).innerHTML = "can't do it"; 
     } 
    } 
} 
  • j'importer dans un document html comme ceci:

    <head> 
        <script type="text/javascript" src="contact.js"></script> 
    </head> 
    
  • et de l'utiliser comme ceci:

    <body id="para"> 
    
    <script type="text/javascript"> 
        contact.getData("http://localhost/~olatunjigbadamosi/Books/contact.txt"); 
        contact.storeData(); 
        contact.displayData("para"); 
    </script> 
    

Répondre

3

Étant donné qu'il est asynchrone, la création de la requête HTTP dans le fichier texte prend du temps. Par conséquent, le rappel contact.storeData est appelé AFTER contact.displayData.

La solution consiste à l'appeler simplement à l'intérieur de storeData, de sorte qu'il se déclenche après avoir fait la requête HTTP dans le fichier texte et rempli la propriété txtDoc.

storeData : function() 
{ 
     if(contact.XMLHttp.readyState == 4 && contact.XMLHttp.status == 200) 
     { 
       contact.XMLDoc = contact.XMLHttp.responseXML; 
       contact.TXTDoc = contact.XMLHttp.responseText; 
    contact.displayData("para"); 
     } 
}, 

code complet qui fonctionne pour moi:

<p id="para"></p> 
<button id="foo">go</button> 
<script> 
var contact = 
{ 
     XMLHttp : null, 
     XMLDoc : null, 
     TXTDoc : null, 

     getData : function(dataSource) 
     { 
       contact.XMLHttp = new XMLHttpRequest(); 
       contact.XMLHttp.open("GET", dataSource, true); 
       contact.XMLHttp.onreadystatechange = contact.storeData; 
       contact.XMLHttp.send(null); 
     }, 

     storeData : function() 
     { 
       if(contact.XMLHttp.readyState == 4 && contact.XMLHttp.status == 200) 
       { 
         contact.XMLDoc = contact.XMLHttp.responseXML; 
         contact.TXTDoc = contact.XMLHttp.responseText; 
       contact.displayData("para"); 
       } 
     }, 

     displayData : function(elementID) 
     { 
       if(contact.TXTDoc != null) 
         document.getElementById(elementID).innerHTML = contact.TXTDoc; 
       else{ 
       document.getElementById(elementID).innerHTML = "can't do it"; 
       } 
     } 
}, 
button = document.getElementById('foo'); 
button.onclick = function() { 
    contact.getData("http://localhost/file.txt"); 
    contact.storeData(); 
}; 

</script> 
+0

Que faire si je veux seulement affecter les réponses de 'XMLHttp' à' XMLDoc et TXTDoc' dans la fonction de rappel au lieu de les afficher? Mon approche qui consiste à insérer les instructions de 'storeData' dans une fonction anonyme attachée à' onreadystatechange' ne semble pas fonctionner. – Fortisimo

+0

'contact.XMLHttp.onreadystatechange = contact.storeData' Définissez une autre méthode qui appelle à la fois storeData et displayData,' contact.ajaxCallback' ou quelque chose de ce genre. –

1

Lorsque vous faites cela de façon synchrone:

contact.getData("http://localhost/~olatunjigbadamosi/Books/contact.txt"); 
contact.storeData(); 
contact.displayData("para"); 

getData est appelée, la demande est envoyée et retourne, getData retourne après la fin puis storeData et displayData s'exécutent. Lorsque vous le faites async, getData lance la requête et retourne immédiatement. Ensuite, storeData et displayData sont appelés avant d'être prêts, ils ne fonctionnent donc pas. Les résultats de la demande ne sont pas encore retournés.

Comme dit meder, pour le réparer, vous devez faire votre affichage dans la fonction de rappel. Cela garantit que les résultats de la requête sont disponibles lors de l'exécution de displayData.

+0

que se passe-t-il si je construis une instruction if dans mon fichier html qui vérifie que getData est prêt avant d'appeler storeData et displayData? Comment ferais-je cela? – Fortisimo

+0

Vous pouvez ajouter une boucle while qui vérifie la fin et le sommeil, mais cela empêcherait tout chargement de votre script jusqu'à ce qu'il soit terminé. Il est préférable de s'en tenir à l'événement conduit/rappel en utilisant le modèle. Vous pourriez avoir le callback modifier le html quand il est appelé. – BaroqueBobcat