2009-09-10 7 views
2

J'essaie d'implémenter un client de chat en utilisant JavaScript. Le client est construit en utilisant le constructeur suivant:XmlHttpObject ne change pas son readyState

function ChatClient(endpointUrl) { 
    this.xmlHttp = createXmlHttpRequest(); 
    this.endpointUrl = endpointUrl; 

    me = this; 
    setInterval('me.receiveMessages()', FETCH_MESSAGES_INTERVAL); 
} 

function createXmlHttpRequest() { 
    /* Create a new XMLHttpRequest object to talk to the Web server */ 
    var xmlHttp = false; 
    /* @cc_on @ */ 
    /* 
    * @if (@_jscript_version >= 5) try { xmlHttp = new 
    * ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlHttp = new 
    * ActiveXObject("Microsoft.XMLHTTP"); } catch (e2) { xmlHttp = false; } } 
    * @end @ 
    */ 

    if (!xmlHttp && typeof XMLHttpRequest != 'undefined') { 
     xmlHttp = new XMLHttpRequest(); 
    } 

    return xmlHttp; 
} 

Le client de messagerie instantanée devrait être en mesure de demander des messages à partir du serveur dans un intervalle défini par l'FETCH_MESSAGES_INTERVAL. Voici le code:

ChatClient.prototype.receiveMessages = function() { 
    this.xmlHttp.open('GET', this.endpointUrl, true); 
    this.xmlHttp.onreadystatechange = this.handleReceiveMessagesResponse(); 
    this.xmlHttp.send(null); 
} 

ChatClient.prototype.handleReceiveMessagesResponse = function() { 
    console.log("readyState = " + this.xmlHttp.readyState); 

    if (this.xmlHttp.readyState == 4) { 
     var rawResponse = this.xmlHttp.responseText; 
     document.getElementById('OutputArea').textContent = rawResponse; 
    } 
} 

Le problème est que lorsque l'handleReceiveMessagesReponse est appelée, le cosole Firebug montre que this.xmlHttp.readyState est toujours 1 (chargement). FireBug montre également que mes requêtes GET reçoivent les réponses attendues du serveur (statut 200 avec la chaîne 'Hello' comme corps). Est-ce que quelqu'un sait ce qui ne va pas avec ce code?

Répondre

1

Vous appelez la méthode handleReceiveMessagesResponse et vous affectez la valeur de retour (undefined) à la propriété onreadystatechange. Je suppose que vous n'aviez pas l'intention de quitter le() à la fin de cette ligne. Cependant cela ne fonctionnera toujours pas car le contexte this ne sera pas ce que vous attendez de la fonction appelée.

Essayez ceci: -

ChatClient.prototype.receiveMessages = function() { 
    var self = this; 
    this.xmlHttp.open('GET', this.endpointUrl, true); 
    this.xmlHttp.onreadystatechange = handleReceiveMessagesResponse; 
    this.xmlHttp.send(null); 


    function handleReceiveMessagesResponse() { 
    console.log("readyState = " + self.xmlHttp.readyState); 

    if (self.xmlHttp.readyState == 4) { 
     var rawResponse = self.xmlHttp.responseText; 
     document.getElementById('OutputArea').textContent = rawResponse; 
    } 
    } 
} 
+0

Cela a fonctionné, merci! Une dernière question de quelqu'un qui est nouveau pour javascript et ajax: est-ce une pratique courante pour implémenter un gestionnaire de réponse comme une fermeture, ou il y a une faille dans ma conception de chat? –

+0

Pratique courante de nos jours de ne pas essayer de construire ce genre de code vous-même, mais d'utiliser un cadre existant comme JQuery qui simplifie énormément ce genre de chose. Cela étant dit, je n'utilise pas JQuery après avoir passé de nombreuses années à mettre en place un cadre interne et, oui, de telles implémentations utilisent des fermetures à bon escient. – AnthonyWJones

0

Cette ligne:

this.xmlHttp.onreadystatechange = this.handleReceiveMessagesResponse(); 

devrait être:

this.xmlHttp.onreadystatechange = (function(fn) { 
    return function() { 
    fn.handleReceiveMessagesResponse.apply(fn, arguments); 
    }; 
})(this); 

Du haut de ma tête. Le raisonnement derrière cette folie:

  • onreadystatechange accepte uniquement les valeurs Function. L'appel de la fonction renvoie sa valeur de retour respective. Puisque vous voulez conserver la référence à this, nous devons l'encapsuler soit en l'affectant à une variable, soit en l'encapsulant dans une fonction de fermeture, cette dernière étant ce que j'ai fait.
  • Nous pouvons ensuite modifier le contexte de la variable 'this' pour la méthode handleReceiveMessagesResponse en utilisant apply/call. Je passe également dans les arguments au cas où ...
Questions connexes