tdc
tdc

Reputation: 5464

Don't execute rest of code until external script loads

I'm working on a tiny bookmarklet script (one big IIFE ). The script was previously created for pages that contain jQuery, and uses jQuery extensively.

The problem is we are now beginning to move away from jQuery in some of our products, but still need this bookmarklet to function the same way.

So, I want to update the bookmarklet so that it will first check if jQuery exists on the page.

if jQuery, continue execution as normal.

If !jQuery, download jQuery (AJAX), THEN execute the rest of the script.

The problem is I'm not sure how to do this inside of an IIFE. Since fetching the script would be an async action, how do I make sure jQuery is downloaded and good to go before continuing the script? This is what I have so far..

(function () {
    var continueExec = true;
    if (!window.jQuery) {
        continueExec = false;
        var s = document.createElement('script');
        s.onload = function () {
            continueExec = true;
        };
        s.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
        document.head.appendChild(s);
    }
        // .. now I want to be able to use jQuery here. What do I need to change?
        // $('.className')...
})()

note that since this is a bookmarket, it gets injected into the page after load/render, so it's not as simple as placing a jQuery script block higher in the head.

Upvotes: 1

Views: 80

Answers (1)

jantimon
jantimon

Reputation: 38160

In javascript you need a callback to handle async operations.

In your example we can execute such a callback for two scenarios:
a) jQuery is already defined
b) jQuery was downloaded and is ready to use

So we change your code a little bit and pass a callback to the IIFE which contains the main application and call it for both scenarios.

(function (callback) {
    if (!window.jQuery) {
        var s = document.createElement('script');
        s.onload = function() {
          // Start the main application once jQuery was load:
          callback(window.jQuery);
        };
        s.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
        document.head.appendChild(s);
    } else {
      // Start the main application directly as jQuery is already part of the page:
      callback(window.jQuery);
    }
})(function($) {
    // The main application
    //
    // here you can use
    // $('.className')...
});

Upvotes: 3

Related Questions