SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question oo xmlhttprequest

    Yesterday I started rewriting the xmlhttprequest functions to an oo equivalent, but as it turns out, I don't get it right:

    Code:
       function Request()
       {
          this.req=init();
          this.req.onreadystatechange = this.processedRequest;
          //addEventHandler/attachEvent alternative
          //doesn't work either
       
          function init()
          {
       	  try
       	  {
       		 if(window.XMLHttpRequest)
       			return new XMLHttpRequest();
       		 else
       			return new ActiveXObject("Microsoft.XMLHTTP");
       	  }
       	  catch(e)
       	  {
       		 alert(e);
       	  }
          }
       }
       
       Request.prototype.send=function(url)
       {
          this.req.open("GET", url, true);
          this.req.send(null);
       }
       
       Request.prototype.processedRequest=function()
       {
          if (this.req.readyState == 4)
          {
       	  if(this.req.status == 200)
       	  {
       		 response=this.responseXML;
       		 res=response.getElementsByTagName('result')[0].firstChild.data;
       		 func=response.getElementsByTagName('feedTo')[0].firstChild.data;
       		 eval(func+'('+result+')');
       	  }
       	  else
       	  {
       			alert(this.req.statusText);
       		}
       	}
       }
    expected usage:
    Code:
       var x=new Request();
       x.send(url); //the processing function
       //the eventtrigger should activate the callback function 
       //when the xml has been returned
    It seems like the problem is that I don't get to my "this.req" in the processedRequest function. Can anyone see where the problem lies, it has been turning me crazy all weekend already.
    Attached Files Attached Files

  2. #2
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was thinking this would be easy, but I really can't figure it out...
    I must be missing something, but what is it?

  3. #3
    SitePoint Addict
    Join Date
    May 2004
    Location
    Europe
    Posts
    216
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    onreadystatechange is not your Request's event, it belongs to the XMLHttpRequest. So in the Request.prototype.processedRequest function, this is a reference to the XMLHttpRequest, you don't need to (and can't) use this.req here.
    And as usual, eval() isn't needed:
    Code:
    if (typeof window[func] == "function")
        window[func](result);

  4. #4
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The common technique of attaching event handlers which are methods of some object is to 'lock' object's reference in a closure:

    Code:
    // BAD
    // the method is bound to an event, 
    // but will be called in context of  AnOtherObject
    // not in "my" context
    
    function SomeObject {
        AnOtherObject.someEvent = this.eventHandler
    }
    
    // GOOD
    // 'this' locking ensures that
    // "my" event hander will be called in "my" context
    
    function SomeObject {
        var locked_this = this;
        AnOtherObject.someEvent = 
                    function() { 
                           locked_this.eventHandler() }
    }

  5. #5
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thanks for the replies, I'll try it out tonight, hope I'll get it right then...

    btw stereofrog: If you want to use addEventHandler/attachEvent (I'm really trying to do it the nice way (but maybe I'm going in over my head )), how can you lock the this-object in there?

  6. #6
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It still doesn't work; What am I doing wrong?

    Code:
         function Request()
         {
      	  this.req=init();
      var lock=this;
      	  this.req.onreadystatechange = function(){lock.processedRequest};
      	  //addEventHandler/attachEvent alternative
      	  //doesn't work either
         
      	  function init()
      	  {
      		 try
      		 {
      			if(window.XMLHttpRequest)
      			   return new XMLHttpRequest();
      			else
      			   return new ActiveXObject("Microsoft.XMLHTTP");
      		 }
      		 catch(e)
      		 {
      			alert(e);
      		 }
      	  }
         }
         
         Request.prototype.send=function(url)
         {
      	  this.req.open("GET", url, true);
      	  this.req.send(null);
         }
         
         Request.prototype.processedRequest=function()
         {
      	  if (this.req.readyState == 4)
      	  {
      		 if(this.req.status == 200)
      		 {
      			response=this.responseXML;
     			res=response.getElementsByTagName('result')[0].firstChild.data;
     			func=response.getElementsByTagName('feedTo')[0].firstChild.data;
      			window[func](result);
      		 }
      		 else
      		 {
      			   alert(this.req.statusText);
      		   }
      	   }
         }
    btw: I really love the 'window[func](result)'-construction, I had never seen it before...

    I don't quite get it all yet, but hope to be as good as you guys once...

  7. #7
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    this.req.onreadystatechange = function(){lock.processedRequest()};

  8. #8
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was searching for some sources around the net about the this "window[func]();"-construction and locking but couldn't find any... Does anyone know where I could find some tutorials?

  9. #9
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The correct term for "locking" is "lexical closure". window[x] is a common javascript property-reference syntax. BTW you don't need any "windows" in your code, because globals are always visible in functions
    Code:
    if (typeof(someGlobalVar) == "function")
        someGlobalVar();

  10. #10
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was searching for some sources around the net about the this "window[func]();"-construction and locking but couldn't find any... Does anyone know where I could find some tutorials?
    I haven't read anything on the net that I consider very good. However, in "Javascript: The Definitive Guide" a closure is described succinctly as: a function executes in the scope in which it is defined. So, in this code:
    Code:
    function SomeObject {
        var locked_this = this;
        AnOtherObject.someEvent = 
                    function() { 
                           locked_this.eventHandler() }
    }
    the function in red is defined within the scope of SomeObject(), and therefore it can see the local variables of SomeObject(). That's nothing too surprising. However, what may be surprising is that if the red function is called and executed at some time in the future, it will still be able to see the local variables that existed at the instant the red function was defined, which was when the assignment was executed. Even if the red function is called and executed long after SomeObject() has finished executing, the red function will still be able to see the local variables at the time it was defined. Therefore, in the code sample above, the variable locked_this will still retain the 'this' reference when the red function is called and executed at some time in the future. Note that any function parameters are also local variables and would be visible to the red function as well.

    The process that preserves the local variables that exist at the time the function is defined is called a 'closure'.

  11. #11
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    if (typeof(someGlobalVar) == "function") someGlobalVar();
    But in my xmlhttpRequest example the someGlobalVar-variable is a string, which would be like writing:

    HTML Code:
    <html>
    <head>
    <script>
    function tryIt()
    {
    	document.getElementById('pp').innerHTML='yes'; //only for testing
    }
    
    function go()
    {
    var a="tryIt";
    if (typeof(a) == "function")
    a();
    }
    
    window["onload"]=go; //really love the window[] thingy
    </script>
    </head>
    <body>
    <span id="pp"></span>
    </body>
    </html>
    That is if I understand it right. On the otherhand, what I did get from your post stereofrog is:

    HTML Code:
    <html>
    <head>
    <script>
    function tryIt()
    {
    	document.getElementById('pp').innerHTML='yes'; //only for testing
    }
    
    onload=go;
    </script>
    </head>
    <body>
    <span id="pp"></span>
    </body>
    </html>
    this thing works!

  12. #12
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I still can't get it right with the addEventListener-method:
    this.req.addEventListener('readystatechange',function(){lock.processedRequest()},false);

    Then I thought, why not put a lock on this function:
    var f=function(){lock.processedRequest()};
    this.req.addEventListener('readystatechange',f,false);

    Or try and access it directly:
    this.req.addEventListener('readystatechange',lock.processedRequest,false);

    But none of these methods worked?!

    And that while I used to think I knew javascript...

  13. #13
    SitePoint Guru momos's Avatar
    Join Date
    Apr 2004
    Location
    Belgium
    Posts
    919
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    function Request()
    {
       this.req=init();
       var lock=this;
       this.req.onreadystatechange = function(){lock.processedRequest};
       //addEventListener/attachEvent still doesn't work
         
       function init()
       {
          try
          {
             if(window.XMLHttpRequest)
                return new XMLHttpRequest();
             else
                return new ActiveXObject("Microsoft.XMLHTTP");
          }
          catch(e)
          {
             alert(e);
          }
       }
    }
         
    Request.prototype.send=function(url)
    {
       this.req.open("GET", url, true);
       this.req.send(null);
    }
         
    Request.prototype.processedRequest=function()
    {
       if (this.req.readyState == 4)
       {
          if(this.req.status == 200)
          {
             response=this.responseXML;
             res=response.getElementsByTagName('result');
             var i=0;
             var result=new Array();
             while(res[i])
                result.push(res[i++].firstChild.data;
             func=response.getElementsByTagName('feedTo')[0].firstChild.data;
             window[func](result);
          }
          else
          {
             alert(this.req.statusText);
          }
       }
    }
    This is my final result ,just so people can use it...

    Maybe some more side-notes:
    Everytime you want to do a call you have to make a new request-object (because this object gets filled up.
    On the server you create a function that generates a xml that looks like this:

    Code:
    <response>
       <result></result>
       <result></result>
       <result></result>
       <feedTo></feedTo>
    </respons>
    The feedTo-function(name of the javascript-function) can then be called on the client to post-process your call.

    (Thanks again for all the help)


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •