'Undefined' when returning object from JS module

375 views Asked by At

I have defined a global variable and then set it equal to a method made available through one of my modules which renders a chart. The module should return a chart, thus assigning the variable 'alChart' a chart object. It is also worth mentioning that the chart renders perfectly fine with this code.

Chart Render module:

var ChartRendererGateway = (function ($, Highcharts) {

"use strict";

//Private variables
var chart;
var result;

//Private methods
var success = function (data, textStatus, jqXHR) {

    var seriesObject = $.parseJSON(data);
    result = seriesObject;

};

var fail = function () {

    errorController.showError("Something went wrong when trying to load the chart data")

};

var drawChart = function (renderTo, options) {
    options.chart.renderTo = renderTo;
    options.series = result;
    chart = new Highcharts.Chart(options);
};

//Public methods
return {

    render: function (renderTo, promise, options) {

        promise.then(success, fail)
            .done(function () {
                drawChart(renderTo, options);
            })
            .fail(function () {
                errorController.showError("Something went wrong fetching chart data!");
            });

        return chart; //Chart object exists here, but is undefined when inspecting variable it is assigned to in the .ready function
    },

    destroy: function(chartName){
        chartName.destroy();
    }
};

})(jQuery, Highcharts);

.ready():

//Global Variables
var alChart;

//DOM Ready
$(function () {

var chartData = ChartDataGateway.getSeries("/Dashboard/GetAssetLiabilityChartData");

alChart = ChartRendererGateway.render("dashboard-AL-chart", chartData,
    {
        chart: {
            type: 'line',
            zoomType: 'xy'
        },
        title: {
            text: null
        },
        xAxis: {
            title: {
                text: 'Date'
            },
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },
        yAxis: {
            title: {
                text: 'Amount'
            }
        },
        credits: {
            enabled: false
        },
        plotOptions: {
            line: {
                allowPointSelect: true,
                cursor: 'pointer',
                marker: {
                    enabled: true,
                    radius: 1,
                    symbol: 'circle',
                    states: {
                        select: {
                            fillColor: '#fff',
                            radius: 4,
                            halo: {
                                size: 4,
                                attributes: {
                                    'stroke-width': 1,
                                    stroke: '#003f72'
                                }
                            }
                        }
                    }
                }
            }
        }
    });
console.log(alChart); //This is returning 'undefined' and NOT the chart object WHY?! :S

});
1

There are 1 answers

0
Seer On BEST ANSWER

I've not done much with jQuery promises before, but I had a crack at this. To chain values, I think you need to create new promises at every step in jQuery (if you do .then().then() you get the same data back in each, not what was returned from the previous .then()). So, every time you need new data, and it's dealing with asynchronous things, if you're altering the data and want to then further alter that, you need to create a new promise to chain from each time.

This is an example of how you can achieve what you want in a basic form:

function doSomething() {
  var deferred = jQuery.Deferred();  

  // Asynchronous action
  setTimeout(function() {    
    deferred.resolve("some data");
  }, 1000);

  return deferred.promise();
}

function doSomethingElse() {
  var deferred = jQuery.Deferred();

  // Has to wait for asynchronous action
  doSomething()
    .then(function(data) {
      console.log(data); // Should be "some data"

      deferred.resolve(data + " that's been added to");
    })
  ;

  return deferred.promise();
}

// Waits for everything to be done that's above, then console.logs end result
doSomethingElse()
  .then(function(data) {
    console.log(data); // Should be "some data that's been added to"
  })
;

You can see this in action here: http://jsbin.com/getiludexe/2/edit?js,console