Search code examples
javascriptjqueryspin.js

spin.js doesn't show up during long running task, but does when I step through the debugger


I'm using spin.js during a long running processing task.

When I just run the task, the UI changes I make immediately before the task runs do not show during the task itself. However, when I manually step through through the process with the debugger, the UI updates as expected. What gives? I tried running a setTimeout on the long running function to give the UI time to update; no dice.

function updateGraphDisplay() {
    var opts = {
        lines: 13, // The number of lines to draw
        length: 20, // The length of each line
        width: 10, // The line thickness
        radius: 30, // The radius of the inner circle
        corners: 1, // Corner roundness (0..1)
        rotate: 0, // The rotation offset
        direction: 1, // 1: clockwise, -1: counterclockwise
        color: '#000', // #rgb or #rrggbb or array of colors
        speed: 1, // Rounds per second
        trail: 60, // Afterglow percentage
        shadow: false, // Whether to render a shadow
        hwaccel: false, // Whether to use hardware acceleration
        className: 'spinner', // The CSS class to assign to the spinner
        zIndex: 2e9, // The z-index (defaults to 2000000000)
        top: '50%', // Top position relative to parent
        left: '50%' // Left position relative to parent
    };

    var spinner = new Spinner(opts).spin();
    $('#chart').append(spinner.el);

    // long running local computations (~4s)

    Highcharts.charts[0].series[0].setData(sentimentDataPoints);
    Highcharts.charts[0].series[1].setData(volumeDataPoints);

    spinner.stop();
}

Solution

  • You have to remember that JS is single threaded. What happens when you use setTimeout(fn, delay) is that JS queues up the function fn to run approximately delay milliseconds in the future, then continues running the lines following setTimeout().

    This means that your updateGraphDisplay() function will run to completion, including creating the spinner and then milliseconds later, removing it. Hence why you don't see it update.

    Instead, what you need to do is move everything after your "long running local computations" into the function passed to setTimeout() so it will execute after that code has run in the future.

    Abbreviated code structure example:

     // initialisation code
     // create spinner and append to DOM
     setTimeout(function () {
         // do calculations
         // update graph
         // clear spinner
     }, 0); // even a delay of 0 will work