2017-06-21 81 views
1

类似的问题是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

我可以考虑制作一个以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 

这样的AJAX调用特定的URL将仅一次,结果将在承诺处理程序之间共享。

+0

谢谢。 IE9支持'.then'吗? – EvilDr

+1

@EvilDr - Per [这个答案](https://stackoverflow.com/a/21585568/2019247),它应该工作,这取决于你使用的是什么版本的jQuery。 – 31piy

+1

那位先生,就像一个魅力!我真的觉得我在那里学到了有价值的东西。谢谢。 – EvilDr