anthonyc
anthonyc

Reputation: 187

Render JQuery DOM changes as they happen

I have a process which loops and collects information using various http GET requests - fired via Ajax with async off as each request depends upon the result of the last. I update a table with the result of each request. The behaviour is variable and I don't understand why. In Firefox the table updates dynamically whilst in Chrome it only updates at the end of the loop. However, if I put in a debug break, it updates each turn of the loop in Chrome.

I prepared this stripped down example - which exhibits the errant behaviour. Strangely it does not work in Chrome or Firefox - ie it only displays the whole table when completed and not as each line is inserted.

<button type="button" id="go">go!</button>

<div>
    <table id="results">
        <tbody id="resultbody">
        <tr>
            <th>Col1</th><th>Col2</th>
        </tr>
        </tbody>
    </table>

</div>

And the JavaScript is

$(document).ready(function() {  

$("#go").click(function(){
    for ( var i = 0; i < 10; i++) {
        $("#resultbody").append("<tr><td>"+i+" Hello</td>" +    "<td>World</td>");
        dosomething(1000);
    }
})

});

function dosomething(miliseconds) {
    var currentTime = new Date().getTime();
    while (currentTime + miliseconds >= new Date().getTime()) {
    }
}

I would expect this to update the brower with each line and then wait for 1 second. In fact, it waits for 10 seconds then shows the whole table. Advice appreciated.

Upvotes: 0

Views: 156

Answers (1)

John S
John S

Reputation: 21482

Because your ajax calls are syncrhonous, they are all processed as part of the same browser event. The browser may choose to wait to update the viewport until it is finished processing that event. It appears Chrome chooses to wait, unless you insert a debug breakpoint, at which time it updates the viewport.

You could try using setTimeout() to push each ajax call to a subsequent event. That would give the browser a chance to update the viewport between the calls, but the calls would not really be synchronous then. That is, they would execute concurrently, rather than consecutively.

Instead, you should switch to asynchronous ajax calls, but initiate the next call when the first call returns, and so on. Something like this.

$(document).ready(function () {
    function makeAjaxCall(i) {
        i = i || 0;
        $.ajax('your_url', {
            type: 'post',
            dataType: 'html',
            data: { index: i },
            success: function (html) {
                $('#resultbody').append(html);
                if (i < 9) {
                    makeAjaxCall(i + 1);
                }
            }
        });
    }

    $("#go").click(function () {
        makeAjaxCall();
    });
});

Here is a jsfiddle that shows an example of this.

Upvotes: 2

Related Questions