4

I have to load a third party script that is not critical for displaying the body (say for simplicity that it adds a red background on ".red" divs).

<script src="redify.js" async defer></script>

I need to execute function myRedify(){ $(".red").redify(); } after the script is loaded.

The script is huge and takes long time (say 3 seconds) to load, but once finished I need to see my .red divs became red.

<script src="redify.js" async defer onload="myRedify()"></script>

Is that the recommended way to do it?

Remarks

  • redify.js is a third party script that I can't modify
  • I don't mind if the divs became red not immediately, but after a delay(when the script is loading, 3 seconds - ok)
serge
  • 13,940
  • 35
  • 121
  • 205
  • 2
    After the script is loaded it is _immediately_ executed, so you can place `myPostFunction()` at the end of the script. – Halcyon Nov 19 '15 at 14:59
  • 1
    @r3wt, OP is asking recommended way! – Rayon Nov 19 '15 at 14:59
  • 1
    to be fair, he asked if this is the recommended way and not if this is possible with the code above :) – ins0 Nov 19 '15 at 14:59
  • @ins0 this is the only possible way unless you create the script programattically in javascript and do `script.onload = function(){...`, or as @Halcyon said just call your function at the bottom of the script. – r3wt Nov 19 '15 at 15:00
  • i wasn't asking, but thanks anyway ^^. why not post it as an answer? – ins0 Nov 19 '15 at 15:01
  • Is this script dynamically inserted? If not and its just in the HTML why make it async? – AtheistP3ace Nov 19 '15 at 15:01
  • another possible way would be with a jsonP callback. in the querystring. – r3wt Nov 19 '15 at 15:02
  • 1
    If you have a script B that relies on script A, don't make script A async. That will be inviting trouble. Always load them in a synchronous fashion. – Bwaxxlo Nov 19 '15 at 15:02
  • This kind a question is already answered in this [link](http://stackoverflow.com/questions/14644558/call-javascript-function-after-script-is-loaded) – mmcorrelo Nov 19 '15 at 15:03
  • @Halcyon please see the updated remark – serge Nov 19 '15 at 15:05
  • Thanks mmcorrelo - ugly solution - valuable! – ins0 Nov 19 '15 at 15:07
  • Where is `myPostFunction()` defined? – gfullam Nov 19 '15 at 15:07
  • please see my updates to clarify the question – serge Nov 19 '15 at 15:14
  • Why do you have `async` and `defer`? It is ok for the page to initially load un-redified? – Halcyon Nov 19 '15 at 15:17
  • @Halcyon please see the remarks. Initially the div has no color, then after the script loading becames red – serge Nov 19 '15 at 15:17
  • please note, using `defer` here does nothing. as stated in the [docs for defer](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer): "*This attribute must not be used if the src attribute is absent*" – But those new buttons though.. Feb 03 '23 at 16:30

1 Answers1

0

Your approach works, and by that it has merrit. Is it recommended? Maybe. Your approach has some advantages and some disadvantages:

  • performance: loading of the redify script starts immediately
  • readability: just looking at the HTML it's pretty obvious what's going on
  • the disadvantage is that, if you were to add another library (for example: blueify.js) you have to duplicate the mechanism.

Right now your code is tightly coupled through the myRedify function. You can decouple it by building a simple require strategy:

var libraries = {
    redify: "redify.js",
    blueify: "blueify.js"
};
var lib_bookkeep = {};

function require(library_name, callback) {
    if (lib_bookkeep[library_name]) {
         if (lib_bookkeep[library_name].status === "loaded") {
             callback();
         } else {
             lib_bookkeep[library_name].elem.addEventListener("load", callback);
         }
    } else {
        var script = document.createElement("script");
        script.src = libraries[library_name];
        script.addEventListener("load", function () {
            lib_bookkeep[library_name].status = "loaded";
        });
        script.addEventListener("load", callback);
        document.head.appendChild(script);
        lib_bookkeep[library_name] = {
            elem: script
            status: "loading"
        }
    }
}

require("redify", function () {
    $(".red").redify();
});

require("redify", function () {
    $(".also-red").redify();
});

require("blueify", function () {
    $(".blue").redify();
});
require("blueify", function () {
    require("redify", function () {
        $(".purple").redify().blueify();
    });
});

This allows you to expand on the libraries that you have, and it allows you to use them arbitrarily. This would by the approach that I recommend. If however you just have this once instance, it's probably find to do it like you have, with asynch/defer and onload.

Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • what exactly do you mean by "add a script include and call any callbacks once it's loaded" is it an ajax call? – serge Nov 19 '15 at 17:42
  • @Serge I added a sample implementation. I haven't tested it but it should work in theory. – Halcyon Nov 20 '15 at 00:12