类似的问题一直是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 +。
答案 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处理程序之间共享。