11

Suppose that stuff contains a considerable amount of html including an element that I want to fill in the line following this one:

$("#content").html(stuff);

Can the following line go ahead and fill the element defined in stuff or is it possible that the code is still running?

If the code will have finished running is it still possible that the element won't exist because the browser won't have rendered it yet?

I know that when I'm using .load (for the initial download of the element) that I'll have to use a callback, but the callback which comes with .html() isn't a do-this-when-done thing like they usually are, which is what has left me really confused. Given the similarity between .html and .load and knowing that .load is asynchronous my gut is telling me that .html must be too, but I can't find any indication either way. Please help.

SteveC
  • 351
  • 2
  • 14
  • 9
    `html` method is synchronous. – Ram Jul 30 '14 at 10:44
  • The elements will be present in the DOM when `html()` returns. Be careful, however, of external-resource-bound elements like images which will be present but may not be loaded yet (so dimension-based computations will be wrong). – Frédéric Hamidi Jul 30 '14 at 10:45
  • Even though it's synchronous, if another function runs at the same time (something triggered by some event or similar, i.e. not a line below it), you can still get a race condition where it will precede `.html()` – yuvi Jul 30 '14 at 10:46
  • 2
    @yuvi, you cannot have "another function runs at the same time" in current JS (webworkers excepted, as usual). The handler would have to interrupt the current function, and by definition this means no race conditions. – Frédéric Hamidi Jul 30 '14 at 10:47
  • @FrédéricHamidi well, not always - http://stackoverflow.com/a/2734311/2387772 – yuvi Jul 30 '14 at 10:48
  • @yuvi, in that answer bobince posits that *you do not remain completely in control until you return from the end of your block or function*. That's true, and I did not say the opposite. That's however, a far cry from truly parallel execution. Interrupting a function to run another before giving control back to the first one is more akin to cooperative multi-tasking than true multi-threading. – Frédéric Hamidi Jul 30 '14 at 10:52
  • @FrédéricHamidi I agree with you. I'm just saying in certain (maybe rare) cases, using `.html()` can result in unexpected behavior despite the fact that it's synchronous (though it will never happen within the same block of code). – yuvi Jul 30 '14 at 10:57
  • So if I have code that I don't want the ground shifting under then I should put it in a block or function? – SteveC Jul 30 '14 at 11:17

1 Answers1

5

The answer is already given in the comments, but to explain it a bit:

The html method doesn't call a callback, it's just a function that returns the jQuery object when a parameter is given (or the html content otherwise).

Say for example when stuff is a very large string containing a lot of html and it would slow down your script, the rest of the script will wait until the html is in place.

So what you asked is certainly possible:

var stuff = '<div id="new">This is a placeholder text</div>';
$('#content').html(stuff);
$('#new').text('This is the real text');

But if stuff is loaded through ajax with .load(), the third line must be in the callback to replace the placeholder text as soon as the html is received from the server:

$('#content').load('content.php', function() {
    $('#new').text('This is the real text');
});

which is btw not more than a shortcut for this:

$.ajax({
    url: 'content.php',
    success: function(data) {
        $('#content').html(data);
        $('#new').text('This is the real text');
    }
});
jazZRo
  • 1,598
  • 1
  • 14
  • 18
  • Thanks. As my element filling code doesn't know going in whether the string is available to use .html I've passed it a function that is either passed to the .load callback or is run after the .html. It's that function which will fill the element contained in stuff. – SteveC Jul 30 '14 at 12:09
  • Yes that would be the way to do it, that's exactly what I explained. So your question has been answered? – jazZRo Jul 30 '14 at 12:21