Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load jQuery with JavaScript using Promises

A previous question revealed how to load in jQuery using native JavaScript. I've successfully used the callback code from the answer there, replicated here:

// Anonymous "self-invoking" function
(function() {
    // Load the script
    var script = document.createElement("SCRIPT");
    script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
    script.type = 'text/javascript';
    document.getElementsByTagName("head")[0].appendChild(script);

    // Poll for jQuery to come into existance
    var checkReady = function(callback) {
        if (window.jQuery) {
            callback(jQuery);
        }
        else {
            window.setTimeout(function() { checkReady(callback); }, 100);
        }
    };

    // Start polling...
    checkReady(function($) {
        // Use $ here...
    });
})();

How can I accomplish the same thing using native JavaScript Promises?

The reason I ask is because I suddenly need to chain off of the earlier callback, and it's a friggin' mess. I'm hoping Promises are a better way, and I have no real interest in using a loader framework.

Here's what I've got so far, but the Promise always ends up rejected:

// This code doesn't work quite right.
// Poll for jQuery to come into existance using a Promise
var jQueryReady = new Promise(
    function(resolve, reject) {

      // Load jQuery
      var script = document.createElement('SCRIPT');
      script.type = 'text/javascript';
      script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js';
      document.getElementsByTagName('head')[0].appendChild(script);

      if (window.jQuery) {
        resolve("YAY");
      } else {
        reject("UGH");
      }
    });

jQueryReady.then(
  function(success) {
    console.log(success);
  },
  function(error) {
    console.error("Really helpful error:", error);
  });

(I'm sorry in advance for my complete ignorance.)

like image 648
rydash Avatar asked Jan 06 '16 16:01

rydash


People also ask

How do I load jQuery into JavaScript?

jQuery code is implemented as part of JavaScript scripts. To add jQuery and JavaScript to your web pages, first add a <script> tag that loads the jQuery library, and then add your own <script> tags with your custom code.

Does jQuery support Promise?

jQuery objects can now return a Promise to observe when all animations on a collection have completed.” jQuery provides several methods that support custom animations (for example, the animate(), fadeIn(), and slideUp() methods). Their return value is the jQuery object.

How use jQuery Deferred and Promise?

promise() will attach the methods onto it and then return this object rather than create a new one. This can be useful to attach the Promise behavior to an object that already exists. If you are creating a Deferred, keep a reference to the Deferred so that it can be resolved or rejected at some point.

What is Promise () method?

The . promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended. By default, type is "fx" , which means the returned Promise is resolved when all animations of the selected elements have completed.


2 Answers

Here's a version that makes a simple loadScript() function that returns a promise and then provides a wrapper around it that detects whether jQuery is already loaded:

function loadScript(url) {
    return new Promise(function(resolve, reject) {
        var script = document.createElement("script");
        script.onload = resolve;
        script.onerror = reject;
        script.src = url;
        document.getElementsByTagName("head")[0].appendChild(script);
    });
}

function loadjQuery() {
    if (window.jQuery) {
        // already loaded and ready to go
        return Promise.resolve();
    } else {
        return loadScript('https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js');
    }
}


// Usage:
loadjQuery().then(function() {
    // code here that uses jQuery
}, function() {
    // error loading jQuery
});

Notes on your code:

  1. In your first code block, setting a single timer and assuming that the script will be loaded when that timer fires is like playing roulette. It might work most of the time, but it is not a purely reliable method of doing things. In addition, to be safe, you have to set the timer to a longer period of time than is usually necessary. Instead, you should trigger based on the onload callback of the script. Then you will know exactly when the script is ready with 100% reliability.

  2. In your second code block, your promise version successfully handles the case where jQuery is already loaded, but then rejects() when jQuery must be custom loaded. As you can see from my example, you need to resolve() when the newly loaded script tag has finished loading for your promise to work as desired.

like image 170
jfriend00 Avatar answered Sep 29 '22 23:09

jfriend00


When you have multiple scripts with dependencies, I've found a promise sequence like this works best:

let p1 = loadScript('https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js')
let p2 = loadScript('scripts/moment.min.js')
            
Promise.allSettled([p1, p2])
.then(function() {
    return loadScript('scripts/myScript.js')
}).then(function() {
    console.log('All Scripts Loaded!')
    initMyScript()
})
.catch(error => {
    console.error(error.message)
})


function loadScript(src) {
  return new Promise(function(resolve, reject) {
    let script = document.createElement('script')
    script.src = src
    script.onload = resolve
    script.onerror = reject
    document.head.append(script)
  })
}
like image 32
moose-o Avatar answered Sep 29 '22 22:09

moose-o