EvilDr
EvilDr

Reputation: 9632

Callbacks not calling back

I'm trying to implement a Javascript cache of JSON data retrieved from API calls (adapted from here), in order to display dashboard widgets. The idea is this:

  1. Load the Google Chart script
  2. Once loaded, each dashboard widget calls a respective API to get the JSON data
  3. Cache the JSON data from each API call, in case two (or more) widgets use the same URL, and retrieve the same data
  4. Render each widget's Google chart using the cached JSON data

This is as far as I've got, but my RenderWidgetN() functions are executing. When using Firebug, I can see the calls are made to the /api/... URL's, and data is returned, but I can't then access it.

<script src="https://www.gstatic.com/charts/loader.js"></script>
<script>
var cache = {};
function LoadOrCacheApiData(url, callback) {
    if (!cache[url]) {
        cache[url] = $.get(url).promise();
    }
    cache[url].done(callback);
}

function DisplayData() {
    LoadOrCacheApiData('/api/AverageLevel?TopN=5', 'RenderWidget0');
    LoadOrCacheApiData('/api/ExpiryCountNDays?DaysAhead=7', 'RenderWidget1');
    LoadOrCacheApiData('/api/LoginCount?DaysPrevious=7', 'RenderWidget2');
}

google.charts.load('current', { packages: ['corechart', 'table'] });
google.charts.setOnLoadCallback(DisplayData);


function RenderWidget0() {
    var d = JSON.parse(cache['/api/AverageLevel?TopN=5']);
    alert(d);
    // to do: render content to div
}

function RenderWidget1() {
    var d = JSON.parse(cache['/api/ExpiryCountNDays?DaysAhead=7']);
    alert(d);
    // to do: render content to div
}

function RenderWidget2() {
    var d = JSON.parse(cache['/api/LoginCount?DaysPrevious=7']);
    alert(d);
    // to do: render content to div
}
</script>

I've not used callbacks nor cache before, so there's probably tons of better ways to achieve this. Any advice/help would be appreciated please. I appreciate that this code could be compacted, but just want to get it working before I start this.

Upvotes: 0

Views: 62

Answers (1)

tavnab
tavnab

Reputation: 2734

I think your callbacks are supposed to be the functions themselves, and not the string name of the functions:

function DisplayData() {
  LoadOrCacheApiData('/api/AverageLevel?TopN=5', RenderWidget0);
  LoadOrCacheApiData('/api/ExpiryCountNDays?DaysAhead=7', RenderWidget1);
  LoadOrCacheApiData('/api/LoginCount?DaysPrevious=7', RenderWidget2);
}

I suggest you use the pattern of taking the returned data from the callback's data argument, rather than using your cache object (see documentation for $.ajax). Also, if you provide a dataType of "json" in your call to $.get, then JQuery will parse the result for you. For example:

function LoadOrCacheApiData(url, callback) {
    if (!cache[url]) {
        cache[url] = $.get(url, 'json').promise();
    }
    cache[url].done(callback);
}

// ...

function RenderWidget0(data, textStatus, jqXHR) {
  // no need for `var d = JSON.parse(data);`
  // since JQuery will parse for you

  alert(data);

  // to do: render content to div
}

I'd also be sure you actually need to do caching in your own code. If this is client code, all modern browsers and most other user-agents have their own local caching that takes care of this for you.

Upvotes: 1

Related Questions