开发者

Javascript: How do I retain a reference to a request initiator in a handler?

I'm not a Javascript person normally, but I've been diving in, reading Douglas Crockford's book, and writing some trivial, useful tidbits as Chrome extensions and Node.js (note that this question isn't about either of them).

Right now, I'm trying to figure out how to retain a reference to an object that's initiating an AJAX request, that is: once I set the onload event handler (this is from inside a Chrome extension, so I'm using the base XMLHttpRequest object), is there any way that I can refer back to MyObject in the following example:

MyObject.prototype = {
    PerformAction: function() {
        this.Request = new XMLHttpRequest();
        this.Request.open("GET", this.ConstructUrl(), true);
        // From within ActionResultHandler, 'this' will always be the XMLHttpRequest
        this.Request.onload = this.ActionResultHandler,
        this.Request.send(null);
    }
}

Doing this exactly is going to assign this to be the request object itself, and if I simply introduce a wrapper:

this.Request.onload = function() { ActionResultHandler() };

well, that开发者_运维百科 just isn't going to do anything, because the ActionResultHandler is now out of scope. The reason I'm asking here is because I've only found trivial cases of caller manipulation (e.g. manipulating what this refers to from inside a function), but given that OO-ified Javascript and AJAX are literally everywhere, this has to have to be a known, simple issue, but my Google-fu is failing me here. In C#, events are invoked in the context of whoever attaches to them, not the object firing the event, so this doesn't come up on a daily basis. Perhaps there's a much better JS pattern that avoids this issue entirely?


It's not really clear to me which variable you want to hold a reference to. Here's how you would retain a reference to MyObject in your onload handler:

MyObject.prototype = {
    PerformAction: function() {
        var MyObjectRef = MyObject,
            ActionResultHandler = this.ActionResultHandler;

        this.Request = new XMLHttpRequest();
        this.Request.open("GET", this.ConstructUrl(), true);
        // From within ActionResultHandler, 'this' will always be the XMLHttpRequest
        this.Request.onload = function () {
                ActionResultHandler.apply(MyObjectRef, arguments);
            };
        this.Request.send(null);
    }
}

Edited

Ok, I reread your question again and it seems that you want to execute ActionResultHandler in the context of MyObject, so I tweaked my code to do this.


Have you tried...

this.Request.onload = this.ActionResultHandler.apply(this);

I'm thinking that's what you're looking for (sorry if it's not). Using .apply(this) will point ActionResultHandler to Object.

Check out this article on binding while you're at it! It helped me out a lot.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜