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



之前也问过类似的问题,但我认为它不能克服这种情况的挑战,因为我的函数调用都是在一起的,所以请耐心等待(如果合适,我会删除这个问题)。

我有许多仪表板小部件,每个小部件都进行 $.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+。

我可以考虑以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,并像这样链接您的 promise 处理程序:

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 调用将只进行一次,结果将在承诺处理程序之间共享。

最新更新