最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Call parent object method inside function with callback handler - Stack Overflow

programmeradmin2浏览0评论

I'm calling ParentObject.doSomething() which inturn calls the WebService object to perform some ajax calls, and on success of the ajax call, the callback function is executed. But any parent function inside the callback function fails.

I think this has something to do with scope resolution. I am not able to find a workaround for this problem.

Is there a better architectural style to modularize the ajax services and model?

I've create a jsfiddle also - /

var ParentObject =  {

     doSomething: function(){
         document.write("Inside doSomething <br />");
         var self = this;
         WebServices.firstService("some URL", self.successCallback);
     },

     changeData: function(data){
         //Manipulate data
         document.write("Inside changeData <br />");
     },

     successCallback: function(jsonData){
         document.write("Inside successCallback <br />");
         try {
             //Execution fails at this point. Possibly because of scope resolution
             this.changeData(jsonData);  
         }
         catch (error) {
             console.log(error);
             document.write(error);
         }  
     },
};

var WebServices = {
    firstService: function(url, successCallbackHandler){
        document.write("Inside firstService <br />");
        //Get data using the URL
        //on success call successCallback
        successCallbackHandler("some data");
    }
};


$(document).ready(function() {
    ParentObject.doSomething();

});
​

I'm calling ParentObject.doSomething() which inturn calls the WebService object to perform some ajax calls, and on success of the ajax call, the callback function is executed. But any parent function inside the callback function fails.

I think this has something to do with scope resolution. I am not able to find a workaround for this problem.

Is there a better architectural style to modularize the ajax services and model?

I've create a jsfiddle also - http://jsfiddle.net/bzKXr/2/

var ParentObject =  {

     doSomething: function(){
         document.write("Inside doSomething <br />");
         var self = this;
         WebServices.firstService("some URL", self.successCallback);
     },

     changeData: function(data){
         //Manipulate data
         document.write("Inside changeData <br />");
     },

     successCallback: function(jsonData){
         document.write("Inside successCallback <br />");
         try {
             //Execution fails at this point. Possibly because of scope resolution
             this.changeData(jsonData);  
         }
         catch (error) {
             console.log(error);
             document.write(error);
         }  
     },
};

var WebServices = {
    firstService: function(url, successCallbackHandler){
        document.write("Inside firstService <br />");
        //Get data using the URL
        //on success call successCallback
        successCallbackHandler("some data");
    }
};


$(document).ready(function() {
    ParentObject.doSomething();

});
​
Share Improve this question asked Jul 24, 2012 at 12:21 Anirudh SAnirudh S 731 silver badge3 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 11

Writing self.successCallback doesn't bind the function to self, you have to actually call the function as self.successCallback() to bind the context correctly.

You can do that easily by wrapping the call in a closure which retains access to self:

doSomething: function(){
     document.write("Inside doSomething <br />");
     var self = this;
     WebServices.firstService("some URL", function() {
        self.successCallback();
     });
 },

or in ES5 you can use .bind() which ensures that the this context for successCallback is always the specified parameter:

doSomething: function(){
     document.write("Inside doSomething <br />");
     WebServices.firstService("some URL", this.successCallback.bind(this));
 },

Here is the prettiest way to do it:

WebServices.firstService("some URL", this.successCallback.bind( this ));

However, it's not cross-browser. (read: IE8 and below can't use it)

This is why jQuery has $.proxy:

WebServices.firstService("some URL", $.proxy( this.successCallback, this ));

When the callback function is called, the this is not valid. In javascript, if a function is called with foo.bar(), this will be set to foo, but if you just call foo(), the previously set this will be kept, in your case the element of the event, probably your WebService. To avoid this, you must use closures. You can replace this.changeData(jsonData); by ParentObject.changeData(jsonData);. Closures means than a function can access variable in the scope where the function was defined, so your function can access ParenObject.

A more elegant way could be:

var ParentObject =  {

    doSomething: function(){
        document.write("Inside doSomething <br />");
        var self = this;
        WebServices.firstService("some URL", function(jsonData) {
            document.write("Inside successCallback <br />");
            self.changeData(jsonData);
        }
    },

    changeData: function(data){
        //Manipulate data
        document.write("Inside changeData <br />");
    }
};

You callback function is defined directly in you doSomething function, so you have access to the variable self defined in it, and can call self.changeData().

Another possiblitity is change

WebServices.firstService("some URL", self.successCallback);

to

WebServices.firstService("some URL", function(data){ return self.successCallback(data) });

The basic problem is that, unlike Python, methods Javascript in Javascript forget about their owner object as soon as you pass them somewhere else or set another variable.

if you change this.changeData(jsonData); to ParentObject.changeData(jsonData); it should work.

The reason for the error is that the this variable no longer refers to ParentObject when the AJAX call returns.

An alternative approach is to store a reference to this inside another variable (by convention called that) and change your code to say that.changeData(jsonData);

发布评论

评论列表(0)

  1. 暂无评论