2017-06-21 3 views
1

Eine ähnliche Frage wurde asked before, aber ich glaube nicht, dass es die Herausforderungen in diesem Fall überwindet, da meine Funktionsaufrufe alle zusammen sind, also bitte mit mir ertragen (ich werde löschen die Frage, wenn angebracht).

Ich habe eine Reihe von Dashboard-Widgets, die jeweils einen $ .ajax-Aufruf machen, ein JSON-Ergebnis erhalten und dann das zum Rendern eines Google-Diagramms verarbeiten. Die Widgets können mehrfach verwendet werden, so dass einige duplizierte AJAX-Aufrufe auftreten, z.

Das Problem ist, dass dies mehrere Aufrufe an die gleiche URL generiert, die sehr verschwenderisch ist. Ich sah in der verknüpften Frage, dass ein Objekt verwendet werden kann, um die Ergebnisse zu cachen, aber als ich dies anwendete, schien es nicht zu funktionieren, weil der zweite Aufruf an RenderChart (unmittelbar nach dem ersten) sah, dass es (noch) keine Daten gab im Cache und rief die URL erneut an.

Mein Code ist:

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>'); 
    } 
    }); 
} 

Im Idealfall wäre es gut, die arrayOfArrays Wert zwischenzuspeichern, wie an dieser Stelle alle weiteren Verarbeitung auch abgeschlossen ist. Wenn ich jedoch JavaScript erhalte, um zu sehen, welche anderen API-Aufrufe gerade ausgeführt werden, und auf sie warten, muss ich mich anstrengen. Ist das möglich?

Wenn mich jemand erreichen kann, werde ich einen Bonus auf die Frage stellen. Ich lese über promises, aber ich muss IE9 + unterstützen.

Antwort

1

Ich kann eine Cache-Map mit URL als Schlüssel und der AJAX-Anforderung als Wert erstellen. Wir können Ihre LoadDataFromApi Funktion ändern, um diesen Cache zu nutzen, und eine entsprechende AJAX-Anfrage zurückgeben, falls sie existiert, andernfalls eine neue Anfrage machen.

Folgendes ist ein Ausschnitt davon, wie es gemacht werden kann.

var requestCache = {}; 

function LoadDataFromApi(apiUrl) { 
    if (!requestCache[apiUrl]) { 
    requestCache[apiUrl] = $.ajax({ 
     type: 'GET', 
     url: apiUrl, 
     dataType: "json" 
    }); 
    } 

    return requestCache[apiUrl]; 
} 

Auf diese Weise können Sie LoadDataFromApi ohne Limit nennen, und die Kette Ihr Versprechen Handler wie folgt aus:

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 

Auf diese Weise der AJAX-Aufruf für eine bestimmte URL wird nur einmal durchgeführt werden, und die Ergebnis wird unter den Verheißungshandlern geteilt.

+0

Danke. Wird ".then" in IE9 unterstützt? – EvilDr

+1

@EvilDr - Pro [diese Antwort] (https://StackOverflow.com/a/21585568/2019247) sollte es funktionieren, abhängig davon, welche Version von jQuery Sie verwenden. – 31piy

+1

Das Sir, funktioniert wie ein Charme! Ich habe wirklich das Gefühl, dass ich dort etwas Wertvolles gelernt habe. Vielen Dank. – EvilDr

Verwandte Themen