How to inject script only once using GWT ScriptInjector?

744 views Asked by At

I have some JavaScript that I want to inject into the DOM when I load up a certain component that uses that script. The component exists in a few places in my app though so it is reasonable for a user to load that component multiple times in a session. Is there a way to prevent the ScriptInjector from loading the same script multiple times?

Important performance question: if I have already loaded a script, does calling inject() on the same script cause the browser to download it a second time or does it realize that it already has the script?

I know that I could create some global variable like FANCY_JS_SCRIPT_LOADED = false; and then in the onSuccess of the callback, call something like FANCY_JS_SCRIPT_LOADED = true; but this seems really, really... heavy-handed.

Docs: http://www.gwtproject.org/javadoc/latest/com/google/gwt/core/client/ScriptInjector.html

1

There are 1 answers

0
Colin Alworth On

Well, if you don't have a "heavy handed" line like that, ScriptInjector itself needs to.

Other options - keep a list of all JS files that have loaded - and never ever remove their <script> tags. Also never accidentally load the same thing from a different domain, different protocol, different version in another part of your code...

But ScriptInjector is meant to be just enough to inject any script, either from a string, or from a URL. If you plan on some reuse of a tool like this, you an wrap it yourself.


Another thought: put the ScriptInjector call in the class initializer block in the class that needs it - GWT will safely compile that so that it is only run once, no matter how many instances of that class are created. This will make it difficult to set up a callback though, depending on how you are using the JS file.

In that case though, you really do want something custom - something like (in nearly-right psuedocode which I haven't run):

private static boolean fancyJsLoaded = false;
public static void loadFancyScript(Callback<Void, Exception> callback) {
  if (fancyJsLoaded) {
     callback.onSuccess();
  } else {
    fancyJsLoaded = true;
    ScriptInjector.fromUrl("path/to/file.js").setCallback(callback);
  }
}