Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will a script tag appended to an element run before the next line after .append()?

I'm fetching an HTML document from the server, storing it in a variable data, then appending it to a <ul> element on the page. Here is what data looks like:

<script>
    hasNext = true // global variable
</script>
<li class="result">one</li>
<li class="result">two</li>

Then in my main Javascript for the page, I do this:

ulElement.append(data);
if (hasNext) {
    ulElement.append(nextPageButton);
}

It seems to work, but I just wanted to make sure that the code in the <script> tag will always run before my if statement. And I couldn't find any info on this possible race condition online. Thoughts?

like image 621
Matt Vukas Avatar asked Sep 30 '15 15:09

Matt Vukas


1 Answers

Independent of whether or not this is a good idea....

In order for the browser to interpret your dynamically inserted DOM, it has to parse the content you are providing. This is a synchronous process (assuming your JS doesn't do any AJAX requests, setTimeouts etc). From the Google Dev blog:

When the HTML parser encounters a script tag, it pauses its process of constructing the DOM and yields control over to the JavaScript engine; once the JavaScript engine has finished running, the browser then picks up from where it left off and resumes the DOM construction.

This means that the browser is guaranteed to process and execute the JS in the script tag (as well as add the DOM in the string) before it moves onto the next JS command: if (hasNext) {....

In your example it wouldn't matter where the <script> tag was in relation to the rest of the dynamically inserted DOM in data because there is no dependency between the DOM and that script. As long as it is in data, the browser will process those commands before proceeding to the line after append. E.g. this would work just as well

<li class="result">one</li>
<li class="result">two</li>
<script>
    hasNext = true // global variable
</script>

Since your code is checking the dynamically 'injected' variable after the append call, the variable (hasNext) is guaranteed to exist (as long as it was in a <script> tag in data).

For example:

$( ".test" ).append( "<p>Test</p><script>var globalVariable = 123;" );
$( ".test" ).append( globalVariable );

will write:

<p>Test</p>123

The most likely race condition is from some server interaction not specifying the hasNext variable, in which case the code will either use the falsey value of that variable:

if (undefined) { 
    alert('I won\'t be called'); 
} else { 
    alert('I will be called'); 
}

-OR, the more risky version-

your if (hasNext) { ... } will use the previous value of that variable from a prior call to append with different data. This is quite risky and possibly the best reason for avoiding this approach.

like image 122
pherris Avatar answered Oct 16 '22 23:10

pherris