4

I have this code for doing an ajax request to a webservice:

var MyCode = {
    req: new XMLHttpRequest(), // firefox only at the moment

    service_url: "http://url/to/Service.asmx",

    sayhello: function() {
        if (this.req.readyState == 4 || this.req.readyState == 0) {
            this.req.open("POST", this.service_url + '/HelloWorld', true);
            this.req.setRequestHeader('Content-Type','application/json; charset=utf-8');
            this.req.onreadystatechange = this.handleReceive; 
            var param = '{}';
            this.req.send(param);
        }
    },

    handleReceive: function() {
        if (this.req.readyState == 4) {
            // todo: using eval for json is dangerous
            var response = eval("(" + this.req.responseText + ")");
            alert(response);
        }
    }
}

It is called with MyCode.sayhello() of course.

The problem with it is that "req is not defined" at the first line in the handleReceive function. It does get called 4 times, so I know the code above sends the request to the server.

How can I solve this?

1
  • Should be this.responseText .. not this.req.responseText (since 'this' refers to the XHR object) Commented May 8, 2009 at 11:40

4 Answers 4

5

Classic closure problem. When you get the callback, the closure actually refers already to the HTTP object.

You can do the following as someone suggests:

var that = this;
this.req.onreadystatechange = function() { this.handleReceive.apply(that, []); };

OR just do the following:

var that = this;
this.req.onreadystatechange = function() { that.handleReceive(); };
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! For the record: working code is: handleReceive: function() { if (this.readyState == 4) { var response = eval("(" + this.responseText + ")"); alert(response); } }
2

You can solve that by makeing a variable refering to this in MyCode. Like

var MyCode = {
    req: new XMLHttpRequest(), // firefox only at the moment

    self = this

    ...
}

Then you can refer to self in stead of this.

Comments

0

Change this:

this.req.onreadystatechange = this.handleReceive;

to this:

var self = this;
this.req.onreadystatechange = function() { self.handleReceive(); }

This creates a closure that should fix your problems.

Comments

0

you should be able to make it work by changing

this.req.onreadystatechange = this.handleReceive;

to

var that = this;
this.req.onreadystatechange = function() { this.handleReceive.apply(that, []); };

Function.prototype.apply can be used to call a function while explicitly this and the function's arguments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.