Nick
Nick

Reputation: 6025

jQuery functions: why is the completion of the first event delayed until a second event finishes?

This has been bugging me for ages, and so I've created a test jsFiddle to illustrate the situation.

The code is as follows:

$('#test').on('click', function() {
    $(this).css('background', 'red');
    for (var i = 1; i < 100000; i++) {
        var el = document.createElement("div");
        el.innerHTML = "Another";
        document.getElementById("container").appendChild(el);
    }
});

Now, I would have thought that the background color should change first, and then the creation of the children would begin. The color doesn't change, though, until after the for loop has finished.

This is not the case, however, if you put a setTimeout delay in place of the for loop.

var timeoutID = window.setTimeout(function () {
    $('#test').css('background', 'blue');
}, 2000);

In the setTimeout case, you see instantaneous red and then blue 2 seconds later. EDIT: Here's the fiddle for the second case.

Why does my first fiddle do what it does? It applies in so many other situations, particularly regarding AJAX.

Upvotes: 1

Views: 98

Answers (3)

Silviu-Marian
Silviu-Marian

Reputation: 10907

You only have 1 main thread in javascript.

Loops block everything from happening, things like queued setTimeouts() or background repaints.

The difference is, setTimeout() doesn't require heavy computations, because it's just a stack, so your 100,000 iterations loops finishes quicker, and allows the next queued function (in this case, the repaint) to execute.

Upvotes: 1

market
market

Reputation: 473

The browser isn't triggering a repaint until the whole of the function has executed.

You can make it repaint before calling the for loop by wrapping the for in a setTimeout with a timeout of zero, like so:

$('#test').on('click', function() {
  $(this).css('background', 'red');
  setTimeout(function(){
    for (var i = 1; i < 100000; i++) {
        var el = document.createElement("div");
        el.innerHTML = "Another";
        document.getElementById("container").appendChild(el);
    }
  }, 0);
});

Upvotes: 3

Pipalayan Nayak
Pipalayan Nayak

Reputation: 957

I have tried a simple modification of it http://jsfiddle.net/Pbgz3/12/ . The color indeed changes before the loop is run. To check that i have decreased the looping iterations.

Upvotes: 0

Related Questions