xmlhttp onreadystatechange not handling "this" properly

D

Dustin

I found a solution to my problem in the topic called "OOP (and the
XMLHttpRequest)". You may find it useful to reference to see what I
have done so far.

I am making a small AJAX helper object called AjaxManager. The purpose
is to make ajax requests easier to use and it also queues them, so you
can tell it to run three requests, one after another and it won't do
the next until the previous is completed.

The problem is here, where the request is created. Here are two
important lines.

currentAjaxManager = this;
this.currentTransport.onreadystatechange = this.handleResponse;

The handleResponse funcion is internal to the AjaxManager object and
looks like this:

AjaxManager.prototype.handleResponse = function()
{
switch (currentAjaxManager.currentTransport.readyState) {
case 0:
if(currentAjaxManager.currentRequest.onUninitialized)
currentAjaxManager.currentRequest.onUninitialized(currentAjaxManager.currentTransport);
break;
case 1:
if(currentAjaxManager.currentRequest.onLoading)
currentAjaxManager.currentRequest.onLoading(currentAjaxManager.currentTransport);
break;
case 2:
if(currentAjaxManager.currentRequest.onLoaded)
currentAjaxManager.currentRequest.onLoaded(currentAjaxManager.currentTransport);
break;
case 3:
if(currentAjaxManager.currentRequest.onInteractive)
currentAjaxManager.currentRequest.onInteractive(currentAjaxManager.currentTransport);
break;
case 4:
alert("Hit case 4. Doing the next request after this.");
if(currentAjaxManager.currentRequest.onComplete)
currentAjaxManager.currentRequest.onComplete(currentAjaxManager.currentTransport);
currentAjaxManager.isBusy = true;
currentAjaxManager.doNextRequest();
break;
default:
alert("There was a problem. Hit an unknown readyState.");
}
}


You'll notice that I reference the object using a closure
(currentAjaxManager) instead of using "this". That is because if I set
onreadystatechange = this.handleResponse, the "this" is not handled
properly. The function is called, but it is called as if it were not a
property of "this" and thus the properties of "this" are not available.
So, if I did that and then, within handleResponse() I referenced the
readyState by this.currentTransport.readyState, it would tell me that
it was undefined.

I have it working by using the closure, but it just hurts my brain to
do it that way. It is horrible practice. For example, if I wanted to
created two AjaxManager objects withing a single page, they would
override each other because they would be using the same "global"
varible to store the currentAjaxManager.

Does anyone know of a special way to reference "this.handleResponse" so
that it will be referenced properly by the xmlhttpobject? Any feedback
will be greatly appreciated.
 
L

Laurent Bugnion

Hi,
I found a solution to my problem in the topic called "OOP (and the
XMLHttpRequest)". You may find it useful to reference to see what I
have done so far.

I am making a small AJAX helper object called AjaxManager. The purpose
is to make ajax requests easier to use and it also queues them, so you
can tell it to run three requests, one after another and it won't do
the next until the previous is completed.

The problem is here, where the request is created. Here are two
important lines.

currentAjaxManager = this;
this.currentTransport.onreadystatechange = this.handleResponse;
[snip]

You'll notice that I reference the object using a closure
(currentAjaxManager) instead of using "this". That is because if I set
onreadystatechange = this.handleResponse, the "this" is not handled
properly. The function is called, but it is called as if it were not a
property of "this" and thus the properties of "this" are not available.
So, if I did that and then, within handleResponse() I referenced the
readyState by this.currentTransport.readyState, it would tell me that
it was undefined.

I have it working by using the closure, but it just hurts my brain to
do it that way. It is horrible practice. For example, if I wanted to
created two AjaxManager objects withing a single page, they would
override each other because they would be using the same "global"
varible to store the currentAjaxManager.

Does anyone know of a special way to reference "this.handleResponse" so
that it will be referenced properly by the xmlhttpobject? Any feedback
will be greatly appreciated.

I think that the way you handled it is correct. Event handlers (not only
the XmlHttpRequest's ones, but generally) don't allow passing
parameters. Closure is, AFAICS, the only way to go.

The problem you mention (overwriting the AJAX manager) can be avoided by
using more than one AjaxManager for the page, and storing them in an
Object, for example. The simple example hereunder demonstrates it.

function AjaxManager( strValue )
{
this.strValue = strValue;
}

function document_Load()
{
document.getElementById( "bn1" ).onclick = bn1_Click;
document.getElementById( "bn2" ).onclick = bn2_Click;
}

var aoAjaxManagers = new Object();

aoAjaxManagers[ "bn1_Click" ] = new AjaxManager( "Value1" );
function bn1_Click()
{
alert( aoAjaxManagers[ "bn1_Click" ].strValue );
}

aoAjaxManagers[ "bn2_Click" ] = new AjaxManager( "Value2" );
function bn2_Click()
{
alert( aoAjaxManagers[ "bn2_Click" ].strValue );
}

and

<input type="button" id="bn1" value="Button 1" />
<input type="button" id="bn2" value="Button 2" />

HTH,
Laurent
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top