3

I am experimenting with Classes available in javascript and have setup a simple test case as follows:

<script src="myclass.js></script>

<script>
    var test = new MyClass();
</script>

myclass.js contains the following:

class MyClass {
    constructor() {
    }
}

This works as expected.

However, if I dynamically load "myclass.js" using jQuery.getScript() function the browser returns the following error:

Uncaught ReferenceError: MyClass is not defined

Things I have double checked are:

The code to instantiate the class is placed within the success callback of the getScript function

And also that the script is actually being loaded and executed (with a simple console log)

However I seem to have a brick wall with this. Is there any reason why a class cannot be instantiated from if the file containing the class is loaded from a javascript file using the jQuery.getScript function?

This is the code which does not work:

<script>
    $(document).ready(function() {
        $.getScript('myclass.js', function () {
            var test = new MyClass();
        });
    });
</script>

Testing on Chrome Version 71.0.3578.98 (64-bit)

Musaffar Patel
  • 905
  • 11
  • 26
  • 2
    Show us your code. – SLaks Dec 30 '18 at 16:18
  • 1
    Add your not-working code (the jQuery) please – Jack Bashford Dec 30 '18 at 16:19
  • My guess is you're trying to use the class before the script is loaded. `getScript` is an asynchronous operation, it works with a callback function that is called after the script has been loaded – Patrick Hund Dec 30 '18 at 16:21
  • I have added the code which does not work to the original question. I already checked the possibility of it being a problem with the asynchronous nature of the injection, however the class is only instantiated in the callback function – Musaffar Patel Dec 30 '18 at 16:55

2 Answers2

1

Have a look at this question and its answers as well as the documentation such says the success callback is run after loading but not necessarily after executing the script.

To sum up, it might suffice to run your code by appending a then (or done) handler:

$.getScript(url).then(function() {
    var test = new MyClass();
});

If this is not enough you should fall back to use a setInterval-triggered check for the existence of the class (stop the interval after finding the class). This way you are avoiding any dependency on the specific browser behavior when the script gets executed after loading it.

function afterScriptExecuted() {
    var test = new MyClass();
}

function testScriptExecuted() {
    return window.MyClass !== undefined;
}

$.getScript(url).then(function() {
    var id = setInterval(function() {
        if (testScriptExecuted()) {
            clearInterval(id);
            afterScriptExecuted();
        }
    }, 50);
});
Hero Wanders
  • 3,237
  • 1
  • 10
  • 14
  • Thanks for the suggestion, I tried this too but to no avail. It's quite strange because the script is loaded and executed by the class MyClass is not usable. – Musaffar Patel Dec 30 '18 at 16:57
  • Ok. I added another workaround to my answer (which was introduced in the mentioned SO answers) using `setInterval`. – Hero Wanders Dec 30 '18 at 17:12
  • Thanks, but this also results in the same error. I even tried increasing the interval. I get the impression this could be related to how the browser registers the class. Perhaps it doesn't register a class name if the script is loaded dynamically. – Musaffar Patel Dec 30 '18 at 17:27
  • It's not necessary to increase the duration between the checks. It's essential to repeat the check until it becomes true. `setInterval` repeats the given callback indefinitely and `clearInterval` (which cancels that cycle) is called only when the class was found. – Hero Wanders Dec 30 '18 at 17:33
  • I see what you mean, testing with your code, window.MyClass always remains undefined so the class is never found. – Musaffar Patel Dec 30 '18 at 19:58
  • Ok, it seems the class constructor is indeed not saved under `window.MyClass`. Perhaps the file is handled as ES module and you would need some kind of import... it's good you've found a solution using the plain old script element loading! – Hero Wanders Dec 30 '18 at 21:19
  • Thanks for the insight and appreciate the help you provided. – Musaffar Patel Dec 30 '18 at 21:21
1

In the end, only the following approach worked for me (rather than using jQuery.getScript)

var script = document.createElement('script');
script.onload = function () {
      var test = new MyClass();
};
script.src = '/myclass.js';
document.head.appendChild(script); 
Musaffar Patel
  • 905
  • 11
  • 26