0

I'm having trouble getting jquery's $.getScript to work. Here's a test file, demo.html:

<!DOCTYPE html>

<script src="/xyz/scripts/jquery-1.11.0.min.js"></script>
<script>
    function wow() { return 3; }
</script>

<h1>Demo</h1>

<script>
    console.log(wow);
    console.log(wow());
</script>

When I browse to this in Chrome on Windows 10, the following is displayed in the console:

Navigated to https://example.org/xyz/tools/demo.html
demo.html:11 ƒ wow() { return 3; }
demo.html:12 3

which is correct.

Then I move the function definition to a file called myModule.js:

function wow() { return 3; }

and create demo2.html, which is demo.html with the function definition replaced by a getScript call:

<!DOCTYPE html>

<script src="/xyz/scripts/jquery-1.11.0.min.js"></script>
<script>
    $.getScript("myModule.js");
</script>

<h1>Demo</h1>

<script>
    console.log(wow);
    console.log(wow());
</script>

This time I get

Navigated to https://example.org/xyz/tools/demo2.html
demo2.html:11 Uncaught ReferenceError: wow is not defined
at demo2.html:11

Am I misunderstanding what $.getScript is for or how it's used?

Addendum

In response to the suggestion to wrap my console.log calls in a $.ready wrapper, I tried the following:

<!DOCTYPE html>

<script src="/xyz/scripts/jquery-1.11.0.min.js"></script>
<script>
    $.getScript("myModule.js");
</script>

<h1>Demo</h1>

<script>
$.ready(function() {
    console.log(wow);
    console.log(wow());
});
</script>

This time I got no error message but, also, the values of wow and wow() weren't written to the console.

Green Grasso Holm
  • 468
  • 1
  • 4
  • 18
  • 2
    It's because `getScript` is asynchronous. Your `console.log`s are executing before `getScript` is done. – Aioros Jan 15 '19 at 20:54
  • Then what good is it? Less dismissively, I do see that there's a parameter for a callback function where the rest of the code in the page can be executed, but what if I'm using getScript to load a dozen modules or more, each with its own success callback, and I need many of them in place before I start running the code that these modules are meant to support? – Green Grasso Holm Jan 15 '19 at 20:58
  • Why do you feel you need to use `getScript` rather than ` – freedomn-m Jan 15 '19 at 20:59
  • For the "loading many scripts and wait for them" scenario, take a look at [this question](https://stackoverflow.com/questions/11803215/how-to-include-multiple-js-files-using-jquery-getscript-method). – Aioros Jan 15 '19 at 21:01
  • @JustinPearce 's answer indicates you don't need to use the callback; you can use `$(doucment).ready(` instead, so no need to handle all the callbacks. – freedomn-m Jan 15 '19 at 21:01
  • eh, i wouldn't trust document.ready with this, there's no guarantee that the the script would load faster than the dom takes to finish being parsed. I would just avoid getScript, imo it's one of the most useless jquery methods available in practice. – Kevin B Jan 15 '19 at 21:15
  • @KevinB I wasn't sure the doc ready also consider ajax requests - didn't seem quite right. – freedomn-m Jan 15 '19 at 22:45
  • As my third example, showed (my addendum to my original post), $.ready didn't work. – Green Grasso Holm Jan 16 '19 at 03:27
  • 2
    @freedomn-m and also Kevin B: I'm trying to use getScript so scripts can load their own dependencies instead of their client HTML pages having to know what they are. In other words, encapsulation, hiding implementation details. – Green Grasso Holm Jan 16 '19 at 03:31

4 Answers4

1

$.getscript

https://api.jquery.com/jquery.getscript/

This is a shorthand Ajax function, which is equivalent to:

$.ajax({
  url: url,
  dataType: "script",
  success: success
});

so $.getscript makes an asynchronous call, so your code is the equivalent of:

  • $.getscript - start loading the script
  • console.log(wow) - can't find it yet as script not yet loaded
  • ... finish loading script

You can use the callback to execute code when the script has loaded:

$.getScript("myModule.js", function() {
    console.log(wow);
    console.log(wow());
});
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • I did see that callback parameter, but its utility seems limited to cases where I'm loading only one external script file, which is a special case. – Green Grasso Holm Jan 15 '19 at 21:01
  • 1
    Ok, wasn't clear from the question. As it's a shortcut for `$.ajax` it also returns a Promise, so you can determine when they have all loaded. – freedomn-m Jan 15 '19 at 21:05
  • Ah! I had to look that up promises, and then I finally came across a solution that had eluded my searches, at https://stackoverflow.com/questions/11803215/how-to-include-multiple-js-files-using-jquery-getscript-method. I'll give the answer that worked. Thanks! – Green Grasso Holm Jan 15 '19 at 21:21
0

The call to getScript() is an asynchronous operation, it does not block the rest of javascript from being executed. You have two options:

1) Wrap the script requiring the content of getScript() in a $(document).ready() to delay execution until everything is loaded.

2) Pass a callback as the second argument to getScript. This callback will be executed if getScript() succeeds.

Justin Pearce
  • 4,994
  • 2
  • 24
  • 37
  • I knew about solution 2 but it's good only for the special case where only one external module is being loaded, so I consider it a weak solution. But now I'm wrapping the calls to console.log() inside a $.ready(function() { ... }); wrapper, and while now I'm getting no error, I'm also getting nothing written to the console. I replaced console.log with alert and still no luck. – Green Grasso Holm Jan 15 '19 at 21:07
  • I've appended the updated code to my original post for reference. – Green Grasso Holm Jan 15 '19 at 21:12
0

getScript is asynchronous method, so you need access its variables in the callback like that:

$.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) {
  console.log( data ); // Data returned
  console.log( textStatus ); // Success
  console.log( jqxhr.status ); // 200
  console.log( "Load was performed." );
});

Your console.log(wow); was executed before the script fully load.

Amr Elgarhy
  • 66,568
  • 69
  • 184
  • 301
0

Thanks to @freedomn-m, who mentioned Promises in a response follow-up comment, I came upon a previous post discussing $.when().done() at How to include multiple js files using jQuery $.getScript() method. This led to script that worked:

<!DOCTYPE html>

<script src="/xyz/scripts/jquery-1.11.0.min.js"></script>
<script>
    $.when(
        $.getScript("myModule.js")
    ).done(function() {
        console.log(wow);
        console.log(wow());
    });
</script>

<h1>Demo</h1>
Green Grasso Holm
  • 468
  • 1
  • 4
  • 18