I am trying to bind onload
and onerror
events of script
tag. This works fine when loading from src. Given the following function:
function injectJS(src, inline) {
var script = document.createElement("script");
if (inline) {
script.innerHTML = src;
} else {
script.src = src;
}
script.onload = function() {console.log("Success!");};
script.onerror = function() {console.log("Error!");};
document.body.appendChild(script);
}
I can easily know whether script has loaded:
> injectJS("https://code.jquery.com/jquery-3.1.1.min.js");
Success!
> injectJS("https://raw.githubusercontent.com/eligrey/FileSaver.js/master/FileSaver.js");
Error!
But when injecting inline JS, with innerHTML, the script doesn't fire the events:
> injectJS("console.log(\"Yes!\");", true);
Yes!
> injectJS("console.log(\"Loaded but error...\"); error;", true);
Loaded but error...
Success!
hasn't been logged in these cases. However, I could just prepend some code that can call a function, for example, once the script is loaded.
The problem comes when there is an error that prevents script from loading in the first place, for example a syntax error:
> injectJS("console.log(\"Success! Or not..\"); syntax error;", true);
Nothing is logged (except the error, of course). How can I detect whether an injected script has loaded or errored out before loading?
Edit:
Oriol's answer has pointed me in the right direction. For reference, here is the final function that works exactly as I wanted and passes the 5 test cases:
function injectJS(src, inline, on_success, on_error) {
var script = document.createElement("script");
script.onload = on_success;
script.onerror = on_error;
if (inline) {
script.innerHTML = "window.script_loaded = true; " + src;
} else {
script.src = src;
}
document.body.appendChild(script);
if (inline) {
var loaded = window["script_loaded"];
window.script_loaded = false;
if (loaded) {
on_success();
} else {
on_error();
}
}
}