i have typescript application dynamically adds script tags point js files. due restrictions cant have these script tags statically defined in html file, add them dynamically through typescript this:
for (let src of jsfiles) { let stag = document.createelement('script'); stag.type = 'text/javascript'; stag.src = src; stag.defer = true; document.body.appendchild(script); }
now, noticing that, when add script tags dynamically, doesn't seem guarantee in order in loaded. unfortunately, jsfiles
array has scripts dependent on each other. so, 2nd script in array can loaded after first 1 loaded. second script references function defined in first one. there way can specify order in scripts ordered , executed when adding them dynamically (similar how ordering done when statically define script tags in html file)?
p.s. avoid using onload callback solve issue since noticed performance degradation application. second script file large , assuming caused degradation.
there ways overcome requirement. can suggest followings:
- use library inject dependencies (amd or commonjs modules)
- create
script
tag programmatically , set attributeasync = false
. - create
script
tag programmatically , set callbackonload
in order react when script has been loaded asynchronously. attributeasync = true
set default. (see example below) - if don't previous options , allowed modify scripts inject, add line @ end of scripts
object
/array
keep track of scripts loaded. - as last resource, can fetch scripts text, build
string
scripts in required order (wrap each text-script inside iife) , execute text-script through horrible , dangerouseval()
. - and worst option, use
setinterval
check whether script executed. added last option because have seen solutions using bad technique.
if working in big project, recommend first option. if have small project, can opt third option. why?
let's consider in second option, setting attribute async = false
cause browser blocking rendering until script has been executed (bad practice).
i want recommend reading script loaders: deep dive murky waters of script loading, half hour worth spending!
i wrote example of small module manage scripts injection, , basic idea behind:
let _scripts = [ 'path/to/script1.js', 'path/to/script2.js', 'path/to/script3.js' ]; function createscripttag() { // gets first script in list let script = _scripts.shift(); // scripts loaded if (!script) return; let js = document.createelement('script'); js.type = 'text/javascript'; js.src = script; js.onload = (event) => { // loads next script createscripttag(); }; let s = document.getelementsbytagname('script')[0]; s.parentnode.insertbefore(js, s); }
in plunker can test injection of scripts asynchronously in specific order:
the main idea create api allows interact scripts inject, exposing following methods:
addscript
: receive url orarray
of url's of scripts.load
: runs task load scripts in specific order.reset
: clear array of scripts, or cancels load of scripts.afterload
: callback executed after every script has been loaded.oncomplete
: callback executed after scripts have been loaded.
i fluent interface or method chaining way, built module way:
jsuloader .reset() .addscript("script1.js") .addscript(["script2.js", "script3.js"]) .afterload((src) => console.warn("> loaded jsuloader:", src)) .oncomplete(() => console.info("* scripts loaded *")) .load();
in code above, load first "script1.js"
file, , execute afterload()
callback, next, same "script2.js"
, "script3.js"
, after scripts loaded, oncomplete()
callback executed.
Comments
Post a Comment