Search code examples
javascripthtmljavascript-injection

Injected Javascript seems to run asynchronously


I'm making a bookmarklet version of a Greasemonkey extension that appends two <script> tags to the page body: the first one is a largish library, the second calls a function from that library.

Generally, it takes two or more attempts (never one, sometimes more than two) to get the script to properly fire. Running the function directly from the console after injecting the library also works. If I check my error logs, I get the message that my injected method doesn't exist yet - hence the title: despite the fact that JavaScript ought to be single threaded, somehow the second method tag is being run first, before the library is done loading.

The bookmarklet code, before minifying, looks like this:

document.body.appendChild(document.createElement('script')).src = "https://my-site-address";

var scrN = document.createElement('script');
var txtN = document.createTextNode("main.Main().main(document.location.href)");
scrN.appendChild(txtN);

document.body.appendChild(scrN);

and the generated html is simply

<script src="https://my-site-address"></script>
<script>main.Main().main(document.location.href)</script>

Solution

  • Use the load event of the script element to execute the function in it:

    var script = document.createElement("script");
    script.onload = function() { main.Main().main(document.location.href); };
    script.src = "https://my-site-address";
    
    document.body.appendChild(script);