Unable to return an object from a .fail() callback?

158 views Asked by At

I am trying to return an object through the _fail callback (Yes, this is meant to run the fail callback), but failSeries is returning as undefined in the console. Any ideas?

var ChartModule = (function ( $, HC, HA, window, undefined) {

//Define public object
var pub = {};

//Private methods
var _getChartData = function (URL, sendData) {

    var xhrObject =  $.ajax({
                            url: URL,
                            type: "POST",
                            data: sendData,
                            success: function (result) { },
                            error: function (jqXHR, textStatus, errorThrown) {}
                        });

    _chartDataResponse(xhrObject);
};

var _done = function (data, textStatus, jqXHR) {
    var seriesObject = $.parseJSON(data);
    return seriesObject;
};

var _fail = function(){
    var failSeries = [];
    var seriesData = {
        data: [{y: 7, id: 'pointAssets', color: '#5c8fb8'}, {y:10, id: 'pointLiabilities', color: '#bb77b5'}, {y:-3, id: 'pointResult', color: '#cc5971'}],
    };
    failSeries.push(seriesData);

    return failSeries;
};

var _chartDataResponse = function(xhrObject){
    xhrObject.then(_done, _fail);
};

var _renderChart = function(renderTo, seriesObject){
    console.log("Chart will be rendered to: '" + renderTo + "'");
    console.log(seriesObject);
};

//Public methods
pub.getChartData = _getChartData;
pub.renderChart = _renderChart;

return pub;
})(jQuery, Highcharts, HighchartsAdapter, window, undefined);

I am then using my module in the following way in an attempt to view the object that has been returned by either the success or fail callabcks:

$(function(){
var x = ChartModule.getChartData("someURL", {test: "test"});
ChartModule.renderChart("breakdown-chart", x);

});

2

There are 2 answers

0
Roamer-1888 On BEST ANSWER

With a slightly better understanding (and use) of $.ajax(), ChartModule will reduce down to far fewer public methods. In particular :

  • be aware that $ajax() returns a promise, which can (and should) itself be returned by getChartData() thus allowing consequential action on success/failure to be taken externally.
  • with appropriare low level error handling in a chained then() inside getChartData() you can make an error message AND the fake seriesData available where ChartModule.getChartData() is called.
var ChartModule = (function ( $, HC, HA, window, undefined) {
    //Private members
    var fakeSeriesData = { data: [{y: 7, id: 'pointAssets', color: '#5c8fb8'}, {y:10, id: 'pointLiabilities', color: '#bb77b5'}, {y:-3, id: 'pointResult', color: '#cc5971'}] };
    function _getChartData(URL, sendData) {
        return $.ajax({
            url: URL,
            type: "POST",
            data: sendData,
            dataType: 'json'
        }).then(null, function (jqXHR, textStatus, errorThrown) {
            var e = new Error(textStatus);
            e.seriesData = getFakeSeriesData();
            return e; //return an augmented Error object.
        });
    }
    function _renderChart(renderTo, seriesObject) {
        console.log("Chart will be rendered to: '" + renderTo + "'");
        console.dir(seriesObject);
        return ...;//something meaningful
    }
    function _getFakeSeriesData() {
        return $.extend({}, fakeSeriesData);
    }
    //Public methods
    return {
        getChartData: _getChartData,
        renderChart: _renderChart,
        getFakeSeriesData: _getFakeSeriesData//make the fake series data directly availalbe.
    };
})(jQuery, Highcharts, HighchartsAdapter, window, undefined);

This strategy will allow control to be execised where ChartModule.getChartData() is called, with no assumptions about what actions might be taken on success or failure of the AJAX other than, on error, to make the fake seriesData available with no knowledge of how/whether it will be used.

Call as follows :

$(function() {
    ChartModule.getChartData("someURL", {
        test: "test"
    }).done(function(seriesData) {
        ChartModule.renderChart("breakdown-chart", seriesData);
    }).fail(function(error) {
        if(error.seriesData) {
            console.log(error.message);
            ChartModule.renderChart("breakdown-chart", error.seriesData);
        } else {
            console.error(error);
            //some othe couse of action
        }
    });
});

At some other point in your code, you could call ChartModule.getChartData() and take completely different actions in response. You could, on error, even inject some other fake seriesData that is, for whatever reason, more appropriate than the default.

3
Bergi On

I am trying to return an object through the _fail callback (Yes, this is meant to run the fail callback). I am then using my module in the following way in an attempt to view the object that has been returned by either the success or fail callabcks:

No. You can't do that. Callbacks don't return anything. See How do I return the response from an asynchronous call?.

but failSeries is returning as undefined in the console.

Because failSeries is a variable that is local to your _fail function, and gets returned to nothing from it.

Any ideas?

Return the promise. And then wait until it resolves before calling renderChart (from a callback).

var ChartModule = (function( $, HC, HA, window, undefined) {

    function getChartData(URL, sendData) {
        return $.ajax({
            url: URL,
            type: "POST",
            data: sendData
        }).then(done, fail);
    }

    function done(data, textStatus, jqXHR) {
        return $.parseJSON(data);
    }

    function fail() {
        // ignore errors, continue with fake data
        return new $.Deferred().resolve([
            {data: [{y: 7, id: 'pointAssets', color: '#5c8fb8'}, {y:10, id: 'pointLiabilities', color: '#bb77b5'}, {y:-3, id: 'pointResult', color: '#cc5971'}]}
        ]);
    }

    function renderChart(renderTo, seriesObject){
        console.log("Chart will be rendered to: '" + renderTo + "'");
        console.log(seriesObject);
    }

    return {
        getChartData: getChartData,
        renderChart: renderChart
    };

})(jQuery, Highcharts, HighchartsAdapter, window, undefined);

$(function(){
    ChartModule.getChartData("someURL", {test: "test"}).then(function(x) {
        ChartModule.renderChart("breakdown-chart", x);
    });
});