I want to mimick this behavior:
<script src="console.log.1.js"></script>
<script>console.log(2)</script>
<script>console.log(3)</script>
That logs out:
1
2
3
Doing this doesn’t work:
<script>
var x = document.createElement("script");
x.src = "console.log.1.js";
x.async = false;
x.defer = false;
document.body.appendChild(x);
console.log("2");
console.log("3");
</script>
It logs out:
2
3
1
The only way I found so far to achieve it:
<script>
document.write("<scrip" + "t src='console.log.1.js'></scrip" + "t>");
</script>
<script>
console.log("2");
console.log("3");
</script>
Is that really the only way to force synchronous loading of external scripts in all browsers? Why doesn’t setting async=false, defer=false work?
UPDATE
FYI, if someone is wondering, the following document.write inception works (in Chrome..):
<script>
// http://jsbin.com/avatiw logs "during"
document.write('<scrip' + 't>console.log("before");document.write("<scrip" + "t src=\\"http://jsbin.com/avatiw\\"></scrip" + "t>");</scrip' + 't>');
document.write('<scrip' + 't>console.log("after");</scrip' + 't>');
</script>
Works and logs out:
"before"
"during"
"after"
Yes, that’s the only way to force the script to load during the page parsing. Or at least, the only way I’d be willing to believe worked well cross-browser.
If your script were like this, I could see your thinking:
…because in theory, when the parser hits the
scriptelement, it suspends everything (because there might bedocument.writestatements) and calls into the JavaScript layer. So you might think, well, adding ascriptelement to the end of thebodyat that point would insert it between the two.But adding a
scriptelement viaappendChildis just fundamentally different, it’s by nature an asynchronous operation (your code continues while the script is being downloaded, which is not the case withscriptelements in the markup barring thedeferorasyncattributes). I can’t point at any one spec to say why, but the behavior you’re seeing is exactly what I’d expect. The treatment ofscriptelements inline with the markup is a bit special.We can see that it’s the download that’s the issue — at least in Chrome — by comparing the result with using a
scriptelement with inline content.Using an external file (live copy | live source):
Result:
Using inline script (live copy | live source — note that I’ve made no attempt to make this cross-browser, it works in Chrome and Firefox as they support the
textproperty onscriptelements):Output: