4

In order to optimize the load of my document, I use to load jQuery async like that

<script async type="text/javascript" src="js/jquery-1.12.3.min.js"></script>

Then I call a script using jQuery :

<script type="text/javascript">
    jQuery(document).ready(function() {
    App.init();
    OwlCarousel.initOwlCarousel();
    FancyBox.initFancybox();
    StyleSwitcher.initStyleSwitcher();
    
    });
</script>

It returns me that jquery is not defined.

I don't know what should I use, I though that .readyfunction would wait until all document is loaded before calling it.

The same for Bootstrap library, It tells me that jQuery is not defined.

I've tried to ask the script to be loaded at the end, but it still does not work properly.

halfer
  • 19,824
  • 17
  • 99
  • 186
Stanislas Piotrowski
  • 2,595
  • 10
  • 40
  • 59

6 Answers6

11

Since jquery script is loaded asynchronously, jquery is not loaded on the moment your script is executing. So you need to wait for it to load by subscribing on load event like this:

<script async id="jquery" type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.js"></script>

Then listen for a load event on this element

<script type="text/javascript">
  document.getElementById('jquery').addEventListener('load', function () {
    App.init();
    OwlCarousel.initOwlCarousel();
    FancyBox.initFancybox();
    StyleSwitcher.initStyleSwitcher();
  });
</script>

But I don't know why someone wants to do things like this.

To optimize page loading speed it is better to put all you javascript at the end of the body, so content will be loaded first, and scripts won't delay page rendering event if it's synchronously loaded.

Edit: I agree with comment and consider previous paragraph not the best way of loading jQuery to the page

Andrey
  • 4,020
  • 21
  • 35
  • 2
    That isn't correct - JS at the end of the body will _start_ loading after the content has loaded, which results in the 'uncanny valley': the page looks loaded but nothing works until the JS has loaded too. That might be desirable in a specific context, but it isn't _always_ better. Meanwhile, a ` – Keith Feb 23 '17 at 10:35
5

Question Script Tag - async & defer has good answer to your problem.

In a nutshell you cannot load jQuery, or other library, asyncronously when some other script depends on it without some additional asyncronous handling for executing the scripts depending on the library.

Community
  • 1
  • 1
ighea
  • 51
  • 4
4

That is my solution:

    <script async type="text/javascript" src="path_to_jquery" id="jquery_script_tag">
    </script>

    <script>
    if ( !('jQuery' in window) )
    {
        window.jQueryQueue = [];
        //define temporary jQuery function
        window.jQuery = function(){
            //just save function parameters to queue
            jQueryQueue.push( arguments );
        }
        document.getElementById('jquery_script_tag').addEventListener('load', function(){
            //call jQuery with parameters saved in queue, after it loaded
            for ( var i in jQueryQueue )
                jQuery.apply( document, jQueryQueue[i] );
        });
    }
    </script>

This code defines a temporary jQuery function if it is yet not defined. The function saves all jQuery function calls to queue while the real jQuery has not yet loaded (instead of calling undefined jQuery function). And when jQuery has loaded, it calls the jQuery functions in the queue with the same parameters as called before.

Xpleria
  • 5,472
  • 5
  • 52
  • 66
Tim Matz
  • 51
  • 4
  • Please explain your solution. What was wrong and how you solved it, rather than simply pasting the code. – Xpleria Oct 18 '17 at 11:17
  • This code caches all jQuery function calls to queue while jQuery have not loaded (instead of calling undefined jQuery function). And when jQuery has loaded - it calls jQuery with the same parameters as it was called before – Tim Matz Oct 19 '17 at 12:46
  • Your explanation should be included in the answer not in the comments. Please edit your answer and include the explanation in it. – Xpleria Oct 19 '17 at 12:49
  • English is difficult for me. Therefore, I write a minimum. Is the new explanation understandable? – Tim Matz Oct 19 '17 at 13:06
  • This seems to be a good solution for function calls, but what if there are property calls like eg. $.event.fixHooks ?? have you found a workaround for these? – itdoesntwork Jan 02 '19 at 13:43
  • I think the only way is to wrap all property calls into jQuery function call: jQuery(function($){ $.event.fixHooks; }); – Tim Matz Jan 09 '19 at 09:49
1

jQuery, and all components that depend on jQuery (including Bootstrap), depend on hooking the DOMContentLoaded event to set up events.

This means jQuery (and anything that uses $(function() {...})) must be downloaded before DOMContentLoaded fires, or it never hooks up its events.

In turn, that means <script async ... will be unreliable, breaking whenever jQuery takes longer to download than the page content does.

Unfortunately <script defer ... doesn't work either thanks to jQuery trying to fire as soon as the document.readyState === "interactive".

You can load content and then load jQuery by putting the <script> at the end of the <body> but this will result in a noticeable pause between the page appearing and any of the jQuery firing - users won't be able to click on anything, visual components won't appear, and so on.

Keith
  • 150,284
  • 78
  • 298
  • 434
-1

This way works just fine:

<script charset="utf-8" type="text/javascript">
var intervalID = window.setInterval(function(){
  if(window.jQuery){
    clearInterval(intervalID);
    console.log('Loaded');
    /* Your code here */
  }
},1000);
</script>
-3

You Used Async Loading When You Try Access Jquery It Not Loaded By Browser You Can Access Jquery After Page Loading Is Complete .

Load Jquery Normally To Fix Your Problem .

Nariman
  • 19
  • 1
  • 3