【问题标题】:Unable to return an object from a .fail() callback?无法从 .fail() 回调中返回对象?
【发布时间】:2014-11-12 16:39:47
【问题描述】:

我正在尝试通过 _fail 回调返回一个对象(是的,这意味着运行失败回调),但 failSeries 在控制台中返回为未定义。有什么想法吗?

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);

然后我以以下方式使用我的模块来尝试查看成功或失败回调返回的对象:

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

});

【问题讨论】:

  • AJAX 是异步的。您无法从回调中返回任何内容,因为 $.ajax 不会等待运行。
  • 那你建议我如何处理这个问题?
  • @MadDawgTom:返回你得到的承诺并等待它解决。
  • 请给我一个例子来说明如何做到这一点?

标签: jquery ajax promise jquery-deferred revealing-module-pattern


【解决方案1】:

随着对 $.ajax() 的更好理解(和使用),ChartModule 将减少到更少的公共方法。特别是:

  • 请注意,$ajax() 返回一个承诺,该承诺本身可以(并且应该)由getChartData() 返回,从而允许在外部对成功/失败采取相应的操作。
  • getChartData() 内的链式then() 中使用适当的低级错误处理,您可以在调用ChartModule.getChartData() 的位置生成错误消息和可用的虚假 seriesData。
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);

此策略将允许在调用 ChartModule.getChartData() 的位置执行控制,而不假设可能对 AJAX 的成功或失败采取什么操作,除非发生错误,以使虚假的 seriesData 在不知情的情况下可用如何/是否使用它。

调用如下:

$(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
        }
    });
});

在代码中的其他位置,您可以调用 ChartModule.getChartData() 并采取完全不同的操作作为响应。如果出错,您甚至可以注入其他一些虚假的 seriesData,无论出于何种原因,它们都比默认值更合适。

【讨论】:

    【解决方案2】:

    我正在尝试通过 _fail 回调返回一个对象(是的,这是为了运行失败回调)。 然后,我以以下方式使用我的模块来尝试查看成功或失败回调返回的对象:

    没有。 You can't do that。回调不返回任何东西。见How do I return the response from an asynchronous call?

    但 failSeries 在控制台中返回未定义。

    因为failSeries 是您的_fail 函数的本地变量,并且不会从中返回任何内容。

    有什么想法吗?

    返回承诺。然后等到它解决后再调用renderChart(来自回调)。

    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);
        });
    });
    

    【讨论】:

    • 请记住,jQuery 的 .then() 不会在返回值时自动将拒绝转换为已完成 - 它只是停留在失败路径上并将返回的值视为“原因”。为了正确处理错误,您需要从fail() 返回$.Deferred().resolve(...) 或在最终的.then() 中包含一个失败处理程序。
    • @Roamer-1888:啊,我总是忘记how broken jQuery deferreds are :-/ 已修复。
    • 是的,它们确实有点不同。
    猜你喜欢
    • 1970-01-01
    • 2016-03-17
    • 2020-08-14
    • 2015-09-12
    • 2019-08-21
    • 2016-01-07
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多