Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XMLHttpRequest using a callback function within an object 1

Status
Not open for further replies.

senorcai

Programmer
Jul 19, 2006
7
GB
Hi All

I've got a working implementation using an XMLHttpRequest to grab some information from an RDF triplestore through a webservice and display it on the page. However, I'm trying to move to a more object-orientated design for the requests as we need to store certain information alongside the requests. As a result I've built a wrapper object 'XmlReq' which is supposed to build and run everything.

The callback function is within this class, however when I try to call any function withint the wrapper class the readyState of the XMLHttpRequest is always 0. This makes me think it is only making the callback once for some reason. Bizarrely if I put exactly the same callback function outside my class then everything runs perfectly fine again.

Code:
function XmlReq(database, query, requestDescription){
	this.database = database;
	this.requestDescription = requestDescription;
	this.url = "";
	if(this.database != null)
		this.url = "../sparql/?database="+this.database+"result-format=sparql&stylesheet=&query-lang=sparql&query=";		
	else		
		this.url = "../sparql/?result-format=sparql&stylesheet=&query-lang=sparql&query=";	
	this.url += encodeForSparQL(query);
	this.xmlrequest = null;
	
	this.executeRequest = executeRequest;
	function executeRequest(){
		this.xmlrequest = false;

		if (window.XMLHttpRequest) { // Mozilla, Safari etc
			this.xmlrequest = new XMLHttpRequest();
			if (this.xmlrequest.overrideMimeType) {
				this.xmlrequest.overrideMimeType('text/xml');
			}
		} 
		else if (window.ActiveXObject) { // IE
			try {	
				this.xmlrequest = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					this.xmlrequest = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {}
			}
		}
		if (!this.xmlrequest) {
			alert('Unable to create XMLHTTP instance');
			return false;
		}
		
		//this only gives readyStates of zero:
		[COLOR=red]this.xmlrequest.onreadystatechange = this.handleResponse();[/color]
		//this works perfectly but the function is outside the class:
		//[COLOR=red]this.xmlrequest.onreadystatechange = function() { processXMLReqChange_new(1, "bla bla"); };[/color]
		this.xmlrequest.open('GET', this.url, true);
		this.xmlrequest.send(null);
	}
	
	this.handleResponse = handleResponse;
	function handleResponse(){
		//this is correct:
		alert("Database: "+ this.database + ". Description: "+ this.requestDescription + ". URL: "+this.url);
		//this always returns zero:
		alert("Ready State: "+this.xmlrequest.readyState);
	}
}

It seems to be necessary to wrap the external call inside an annonymous function, whereas trying to make a function call within a class using an annonymous function won't work.

Any ideas much appreciated! Thanks
SenorCai
 
The problem is that when the event occurs the context of "this" is lost. I solved this problem by using a reference to the object that is external to the object (i.e. an array of objects). Each object knows where it is in the array (it's index), so it knows how to create an external reference to itself. Something like this:
Code:
eval("this.xmlrequest[\"" + onreadystatechange + "\"] = function() { arrayOfObjects[" + this.Number + "].handleResponse(); };");
No guarantees, I'm working from memory here.

Tracy Dryden

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard. [dragon]
 
Thanks tsdragon.

This works for one object in the array but if I do it this way, when I delete an object in the array won't this change the array indexing so that the handleReponse method will be called on a different object to the intended one? I don't know yet as I haven't got quite that far!

SenorCai
 
OK I've now got as far as combining queries together and found that this.Number doesn't work. Nor does there seem to be reference to it or anything similar anywhere. Does anyone know what this function might be called or how to build it?
Thanks
SenorCai
 
Sorry, it was an incomplete example. You have to create your own arrayOfObjects, and each object has to define and maintain it's own Number property (you can also use a string, and "arrayOfObjects" will actually be "collectionOfObjects") and add/remove itself to/from the array.

Tracy Dryden

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard. [dragon]
 
Thanks. I figured that was probably what was going on. Its all working now so thanks a lot!
 
You're quite welcome! It took me hours and hours to figure that one out.


Tracy Dryden

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard. [dragon]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top