使用结果缓存防止重复的$ .ajax调用

时间:2017-06-21 09:37:36

标签: javascript jquery ajax caching

类似的问题一直是asked before,但我不相信它克服了这种情况下的挑战,因为我的函数调用都在一起,所以请耐心等待(如果合适,我会删除这个问题)

我有许多仪表板小部件,每个小部件都进行$ .ajax调用,接收JSON结果,然后处理它以呈现Google图表。小部件可以多次使用,因此会发生一些重复的AJAX调用,例如

RenderChart('/api/LoginCount?DaysPrevious=7', 'ColumnChart'); // some parameters removed, for brevity
RenderChart('/api/LoginCount?DaysPrevious=7', 'AreaChart');
RenderChart('/api/LoginCount?DaysPrevious=7', 'Table');

问题是这会产生对同一URL的多次调用,这非常浪费。我在链接的问题中看到一个对象可以用来缓存结果,但是当我应用它时,它似乎不起作用,因为第二次调用RenderChart(紧接在第一个之后)看到没有数据(还)在缓存中,并再次调用URL。

我的代码是:

function LoadDataFromApi(apiUrl) {
    return $.ajax({
        type: 'GET',
        url: apiUrl,
        dataType: "json",
        success: function (data) { }
    });
}

function RenderChart(apiUrl, chartElementId, chartType, chartOptions) {
    $.when(LoadDataFromApi(apiUrl)).done(function (data) {
        var el = $('#' + chartElementId);
        try {
            var arrayOfArrays = BuildGoogleArrayFromData(data); // Transform JSON into array of arrays (required by Google Visualization)
            $(el).empty();
            if (arrayOfArrays.length == 0) { // Data found?
            $(el).append('<p class="noData">No data was found.</p>');
        } else {
            var wrapper = new google.visualization.ChartWrapper({ // alert(wrapper.getChartType()); // wrapper is the only way to get chart type
                chartType: chartType,
                dataTable: google.visualization.arrayToDataTable(arrayOfArrays, false),
                options: chartOptions,
                containerId: chartElementId
            });
        wrapper.draw();
        }
    }
    catch (ex) {
        $(el).append('<p class="error">An error occurred: ' + ex.message + '</p>');
    }
    });
}

理想情况下,缓存arrayOfArrays值会很好,因为此时所有其他处理也已完成。但是,获取JavaScript以查看正在进行的其他API调用,并等待它们是我正在努力的地方。这有可能实现吗?

如果有人能够帮助我实现这两个目标,我会在问题上加上奖金。我读到了promises,但我需要支持IE9 +。

1 个答案:

答案 0 :(得分:1)

我可以考虑制作一个以URL作为键的缓存映射,并将AJAX请求作为其值。我们可以更改您的LoadDataFromApi函数以利用此缓存,并返回适当的AJAX请求(如果存在),否则请发出新请求。

以下是如何完成的摘要。

var requestCache = {};

function LoadDataFromApi(apiUrl) {
  if (!requestCache[apiUrl]) {
    requestCache[apiUrl] = $.ajax({
        type: 'GET',
        url: apiUrl,
        dataType: "json"
    });
  }

  return requestCache[apiUrl];
}

通过这种方式,您可以无限制地调用LoadDataFromApi,并像这样链接您的承诺处理程序:

LoadDataFromApi('http://fake.url')
  .then(function(data) {
    // use the data in one widget
  })

LoadDataFromApi('http://fake.url')
  .then(function(data) {
    // use this data in another widget
  })

// ... and so on

这样,对特定URL的AJAX调用只会进行一次,结果将在promise处理程序之间共享。