2017-06-21 83 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