Search code examples
jqueryajaxgraphrickshaw

Real Time Graph Not updating in Rickshaw Graph


My code for generate graph is as below:

var allVenues = [];
var seriesData = [];

var callGraph = function () {
    var where = jQuery('#hdnVal').val();
    jQuery.ajax({
           url: "PopulateTable",
           type: 'GET',
           data: {
                 'where': where
           },
           dataType: "json",
           async: false,
           success: function (responseJson) {
                  if (responseJson != null) {
                     jQuery.each(responseJson, function (key, value) {
                            jQuery('#hdnVal').val(value['date']);
                     });
                     allVenues.push(responseJson);
                  }
              }
     });
     var length = 0;
     var length1 = 0;

     var dataXY = [];

     var dataX = [];
     length = allVenues.length;
     for (var i = 0; i < length; i++) {
         length1 = allVenues[i].length;
         for (var j = 0; j < length1; j++) {
             dataX.push([returnTimestamp(allVenues[i][j].date), returnDate(allVenues[i][j].date)]);
             dataXY.push({x: returnTimestamp(allVenues[i][j].date), y: allVenues[i][j].price});
         }
     }
     seriesData = [dataXY];
} ;
callGraph() ;
var palette = new Rickshaw.Color.Palette({scheme: 'classic9'});
var graph = new Rickshaw.Graph({
   element: document.getElementById("chart"),
   width: 900,
   height: 500,
   renderer: 'area',
   stroke: true,
   preserve: true,
   series: [
     {
        color: palette.color(),
        data: seriesData[0],
        name: 'Price'
     }
   ]
});
graph.render();

setInterval(function () {
   callGraph();
   graph.series.addData(seriesData);
   graph.render();
}, 5000);

In this code my "seriesData" array is updating, but the graph is not updating. The generated json array is good for the graph at the time of page load, but when I apply the interval then graph not updating.


Solution

  • In the absence of decent Rickshaw documentation, and no example of asynchronous updating, it's hard to say what will work and what won't.

    It seems unnecessary to maintain the allVenues array unless you want to rebuild the graph from scratch at every update. Adding to the series data and calling .render() should suffice.

    You probably want something like this :

    (function() { // IIFE to isolate from the Global name space, if not otherwise wrapped.
        var jqXHR;
        var errors = {
            count = 0,
            threshold: 10 // number of consecutive error after which the update cycle should die
        }
        var palette = new Rickshaw.Color.Palette({ scheme: 'classic9' });
        var lastDate = jQuery('#hdnVal').val();
        var seriesData = []; // <<<<<<<<<<<< add
        var graph = new Rickshaw.Graph({
            element: document.getElementById('chart'),
            width: 900,
            height: 500,
            renderer: 'area',
            stroke: true,
            preserve: true,
            series: [{
                color: palette.color(),
                data: seriesData, // <<<<<<<<<<<< change
                name: 'Price'
            }];
        });
    
        var callGraph = function (val) {
            if(jqXHR) {
                // In case previous ajax has not responded.
                jqXHR.abort(); // Abort previous ajax and force its error handler to fire.
                return; // Allow the error handler to report the abort error then retry/die.
            }
            jqXHR = jQuery.ajax({
                url: "PopulateTable",
                type: 'GET',
                data: { 'where': val },
                dataType: "json"
            }).then(function (responseJson) { // ajax success handler
                if (responseJson) {
                    // Here's the major guess!
                    // ***** start: delete *****
                    // graph.series.addData(responseJson.map(function(item) {
                        // lastDate = item.date;
                        // return { x: returnTimestamp(item.date), y: item.price };
                    // }));
                    // ***** end: delete *****
    
                    // ***** start: add *****
                    responseJson.forEach(function(item) {
                        lastDate = item.date;
                        seriesData.push({ x: returnTimestamp(item.date), y: item.price });
                    });
                    // ***** end: add *****
                }
                graph.render();
                errors.count = 0; //reset errorCount
                setTimeout(function() {
                    callGraph(lastDate);
                }, 5000);
            }, function(jqXHR, textStatus, errorThrown) { // ajax error handler
                errors.count += 1;
                console.log("callGraph()", textStatus, "errorCount: " + errorCount);
                if(error.count < errors.threshold) {
                    setTimeout(function() {
                        callGraph(lastDate); // retry with same lastDate as previous ajax call.
                    }, 5000);
                } else {
                    // Allow the update cycle to die
                    console.log("callGraph() errorTheshold reached");
                }
            });
        };
    
        callGraph(lastDate);
    })();
    

    Note that due to AJAX's asynchronism, updating the graph and stimulating the next stage of the update cycle is done in the AJAX success handler. setTimeout() is used in lieu of setInterval(), which is more cumbersome when it comes to killing the cycle.

    If it still doesn't work, then the graph.series.addData(...) part is probably at fault. It may just need debugging but alternatively, you could try the two suggestions here - https://stackoverflow.com/a/19126145/3478010