简体   繁体   中英

Javascript multiple function setTimeout syncing problems, or is there a better way?

Ok, so I am having trouble with something. I want to create multiple graphs with CanvasJS utilizing data from one data source. The problem is that I update the graphs every 60 seconds, and when I run the update function it ends up calling my external JSON once for each graph it is updating, which is not ideal. So I tried putting things on separate timer loops to setTimeout every 60 seconds but on two different functions, and it works but I have noticed sometimes the data that gets updated is almost 2 minutes behind, think like 1m 50s behind or so. Which also is not ideal. My code with a lot of brevity looks something like this...

var updatedData = {}; // start empty

function updateData() {
    $.getJSON("/update.php", function (data) {
       updatedData = data; // new data for datapoints
    });
}

function makeGraph(dataValue, color) {
    // ... bunch of code here for making the graph and setting url's to use

    $.getJSON(url, function(data) { // bring in initial data
        $.each(data[dataType], function(k,v) {
            // handle data for each dataType setting datapoints to be graphed
        }
        linechart.render(); // create initial chart
    });

    function updateLineChart() { // ok let's update each chart...

        $.when(updateData()).done(function() {
            // use updated data for new set of datapoints
            linechart.render();// add new data to current chart
        }

        setTimeout(function() {
            updateLineChart(); // run update every 60 seconds
        }, 60000);
    }
    updateLineChart(); // initially run update
}

This works just fine, but unfortunately it calls update.php for every chart it is rendering and udpate.php actually sends the data for all of the charts on every call, so there is no need to call it 3,4,5 times or more every minute. When it calls data like this, the data is kept up to date and is within 1 minute or real-time, so accuracy is good.

I have redone this multiple times trying to get rid of the extra calls through numerous different methods. One that I did which only calls it once but has a good chance of laggy data is like so...

var updatedData = {}; // start empty

function updateData() {

    $.getJSON("/update.php", function (data) {
       updatedData = data; // new data for datapoints
    });

    setTimeout(function() {
        updateData(); // run data update every 60 seconds
    }, 60000);
}

updateData(); // run data update initially

function makeGraph(dataValue, color) {
    // ... bunch of code here for making the graph
    $.getJSON(url, function(data) { // bring in initial data
        $.each(data[dataType], function(k,v) {
            // handle data for each dataType setting datapoints to be graphed
        }
        linechart.render(); // create initial chart
    });

    function updateLineChart() { // ok let's update each chart...
            // use updated data for new set of datapoints
            linechart.render(); // add new data to current chart
        }
        setTimeout(function() {
            updateLineChart(); // run update every 60 seconds
        }, 60000);
    }
    updateLineChart(); // initially run update
}

Doing it this way they are on different setTimeout loops and as such the data still comes near real-time but I have noticed it is often almost a full two minutes behind. Also for the record I have tried setting cheap tricks like creating new dates, seeing if the dates match with utcSeconds(0) and only grabbing update.php if the dates do not match without avail. It still grabs update.php multiple times.

Can anyone think of a way to keep them nicely synced up, running multiple charts and only making a single call to get the data? I am running out of ideas on this one.

Try something like this:

var timeoutId = undefined;//In global scope

//whenever you set new timeout first clear old one and then create new
if (timeoutId) {
    clearTimeout(timeoutId);
}
timeoutId = setTimeout(function() {
    updateData(); // run data update every 60 seconds
}, 60000);

HTH

You can try something along these lines:

    function updateData() {
       return $.getJSON("/update.php", function (data) {
          return data; // new data for datapoints
       });   
    }

    function updateLineChart(lineChartData) { 
        // use updated data for new set of datapoints
        linechart.render(); // add new data to current chart
    }

    function updateGraphs() {
        updateData().then(function(grphData){
            //foreach var crtData in grphData --> not sure who you key the data here                 in your response
        updateLineChart(grphData[cIndex])
        })
    }

    //initiallize with empty data
    //foreach var crtData in grphData --> not sure who you key the data here in your response
    updateLineChart({})

    setInterval(function() {
        updateGraphs(); // run data update every 60 seconds
    }, 60000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM