weixin_33728708 2017-05-09 14:10 采纳率: 0%
浏览 8

回调不回叫

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.

  • 写回答

1条回答 默认 最新

  • weixin_33733810 2017-05-09 14:14
    关注

    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.

    评论

报告相同问题?