-1

Please refer the below example code

var report = {
    chartTypes : null,
    init: function () {
        this.getChartTypes(function(data){
            this.chartTypes = data;
        });
    },

    getChartTypes: function(callback) {
        $.ajax({
            data:'',
            url:'',
            success:function(response){
               chartTypes = JSON.parse(response);
               callback(chartTypes);
            }
        });
    },
    getToolbar:function() {
        this.chartTypes --------------- NULL
    }
}

getChartTypes function load different chart types via AJAX. Therefore i put it as a callback function. Data is received successfully. But when i use this.chartTypes in a different function like getToolbar it says this.chartTypes is null. Even i have initialized the same in the starting. May be scope issue. Please advise.

gurvinder372
  • 66,980
  • 10
  • 72
  • 94
manashb
  • 179
  • 1
  • 1
  • 12
  • This has been answered before here: http://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript – NMunro Jan 04 '16 at 13:21
  • 2
    @NeilMunro this is *not* primarily a scope issue - it's an async issue – Alnitak Jan 04 '16 at 13:22
  • You seem to be assigning a value of the `chartTypes` variable inside the AJAX success callback. So before calling the `getToolbar` function which reads this variable you should make sure that the `getChartTypes` function has been called and the AJAX request has successfully finished executing. – Darin Dimitrov Jan 04 '16 at 13:22
  • 1
    It is neither scope nor async (although there might be an additional async problem). `this.chartTypes` simply doesn't refer to the global variable `chartTypes`. – Quentin Jan 04 '16 at 13:23
  • @Alnitak This is a scope issue too – epascarello Jan 04 '16 at 13:23
  • @Quentin yes, there's that too, but once that's fixed he still has the async problem – Alnitak Jan 04 '16 at 13:23
  • 2
    @Alnitak — Probably, we can't see how the two functions are called in relation to each other though. – Quentin Jan 04 '16 at 13:23
  • Seems weird to use callbacks when you are using an OOP approach. – epascarello Jan 04 '16 at 13:24

2 Answers2

1

You are assigning to a variable (probably global) called chartTypes, but that isn't the same as reoprt.chartTypes. You need to assign to this.chartTypes, but this in your anonymous function won't be the same as this outside it, so you need to remember that value using another variable:

getChartTypes: function(callback) {
    var self = this;
    $.ajax({
        data:'',
        url:'',
        success:function(response){
           callback( self.chartTypes = JSON.parse(response) );
        }
    });
}
Paul
  • 139,544
  • 27
  • 275
  • 264
  • It seems to be working. But getToolbar function is called from two places. For the first time chartTypes contains the expected value. But again it is null. How can we make it global so that it does not became empty. – manashb Jan 04 '16 at 14:03
  • @manashb Maybe you have the async issue as well. Are you calling `getToolbar` before the Ajax response comes back, like `report.getChartTypes(); report.getToolbar();`, that would return null, since the Ajax callback hasn't executed yet. – Paul Jan 04 '16 at 14:17
  • Paulpro there is no async issue. getToolbar is called only after AJAX response comes back. But the AJAX function is called only once and getToolbar function is called two times. First time chartType is not empty but 2nd time it is empty. – manashb Jan 04 '16 at 14:23
  • @manashb Something else must be setting it back to null then. Once it's set it won't be changed unless it is reassigned a new value. Is your `report` object still in scope? (`console.log( report );`) – Paul Jan 04 '16 at 14:32
  • Resolved. Thanx for your reply. it is really helpful – manashb Jan 04 '16 at 14:57
0

With an OOP approach, most developers would use a method and use .bind() to maintain the proper scope when the asynchronous success method is triggered. This way you do not have to worry about closures and using variables to hold the scope of this.

var report = {
    chartTypes : null,
    init: function () {
        this.getChartTypes();
    },

    getChartTypes : function(callback) {
        $.ajax({
            data:'',
            url:''                
        }).done(this._setSuccessResponse.bind(this));
    },

    _setSuccessResponse : function(data){
        this.chartTypes = data;
    },

    getToolbar : function() {
        console.log(this.chartTypes);
    }
}

You also need to make sure that when you call getToolbar that the Ajax call has also been completed.

epascarello
  • 204,599
  • 20
  • 195
  • 236