XmlHttpObject doesn't change its readyState

I am trying to implement a chat client using JavaScript. The client is constructed using the following constructor:

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;
}

      

The chat client must be able to request messages from the server at an interval specified FETCH_MESSAGES_INTERVAL

. Here's the 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;
    }
} 

      

The problem is that when handleReceiveMessagesReponse is called, the constellation FireBug shows this.xmlHttp.readyState is always 1 (loading). FireBug also shows that my GET requests are getting pending responses from the server (status 200 with "Hello" as body). Does anyone know what is wrong with this code?

+2


source to share


2 answers


You call the handleReceiveMessagesResponse method and assign the return value (undefined) to the onreadystatechange property. I suspect that you do not intend this and in fact should leave () at the end of this line. However, this still won't work because the context this

won't be what you expect from it in the called function.

Try this: -



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;
    }
  }  
}

      

+1


source


This line:

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

      

Should be:



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

      

Off the top of my head. The reasons for this madness:

  • onreadystatechange

    takes only values Function

    . The function call will return the appropriate return value.
  • Since you want to keep the reference to this

    , we have to encapsulate it either by assigning it to a variable or by encapsulating it inside a closure function, the last of which is what I did.
  • We can then change the context of the 'this' variable for the method handleReceiveMessagesResponse

    using apply

    / call

    . I also pass arguments just in case ...
0


source







All Articles