【问题标题】:Prevent duplicate $.ajax calls using result cache使用结果缓存防止重复的 $.ajax 调用
【发布时间】:2017-11-24 03:14:36
【问题描述】:

一个类似的问题是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+。

【问题讨论】:

    标签: javascript jquery ajax caching


    【解决方案1】:

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

    以下是如何完成的 sn-p。

    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 处理程序之间共享。

    【讨论】:

    • 谢谢。 IE9 是否支持.then
    • @EvilDr - 根据this answer,它应该可以工作,具体取决于您使用的 jQuery 版本。
    • 那位先生,工作就像一个魅力!我真的觉得我在那里学到了一些有价值的东西。谢谢。
    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 2012-09-29
    • 2019-02-03
    • 2018-05-18
    • 2011-05-22
    相关资源
    最近更新 更多