Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading/Appending JS script asynchronously

I'm using Laravel to implement templates based on a main page. Different pages have different JS scripts, so I created a template to import JS scripts:

<!-- jQuery 2.1.3 -->
<script src="{{ URL::asset('plugins/jQuery/jQuery-2.1.4.min.js') }}"></script>

<!-- Bootstrap 3.3.2 JS -->
<script src="{{ URL::asset('js/bootstrap.min.js') }}" type="text/javascript"></script>

<!-- Ajax Page Loading -->
<script>
    function ajax(url) {
        $('.main-content').fadeOut(100); //hide the page
        $('.spinner').show(); // show a spinner
        $.ajax(url, {
            async: true,
            success: function(data) {
                $('#header').html(data[0]); //append received header to header
                $('#content').hide().html(data[1]).fadeIn(500); //show the page again
                $('body').append(data[2]); //append scripts to body
                $('.spinner').hide();
            },
        });
    }
</script>

@yield('extra-scripts') <--- /* HERE is where the scripts will be */

I'm also using AJAX to load only the content without refreshing the page. The function ajax will be used to load any url into the div "content". However, I also need to load the scripts so the page works properly.

Data is an array with three fields:

  • 0 is Header html
  • 1 is Content html
  • 2 are the dynamically added scripts

The problem is whenever I'm loading the page, I get this error:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

I don't want script loading to affect user experience. Has to be async.

What I already tried:

  • jQuery.getScript

    • This solution requires me to move all the scripts to a separate JS file. This would probably solve it, but I would rather keep them all in the respective page.
  • AjaxPreFilter

    • $.ajaxPrefilter with options.async = true makes the scripts load after the page thus making some properties undefined and not working.
like image 406
Pedro Lourenço Avatar asked Oct 19 '22 13:10

Pedro Lourenço


1 Answers

This warning will continue to happen as long as you inject the script to the body of the document.

I'd recommend using $.getScript as this will load the script correctly. I do not really understand why you'd want all javascripts to be in the same page from the first place. You probably want to have them in a separate file anyway for easier maintenance down the road and separation of concerns.

You can also use vanilla javascript for that:

var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.setAttribute('src','your_script.js');
head.appendChild(script);

If you insist on doing it this way - try injecting it directly to the head of the document and not the body and see if that helps.

On a more general note - seems like you're building a single page application (SPA) - have you looked into JS frameworks like Angular, Backbone, etc? they will handle all the heavy lifting for you and will help you scale your application better. This smells a little bit like trying to re-invent the wheel and could be a great thing as an educational process but might not be such as good idea in the long run.

Hope this helps.

like image 102
dev7 Avatar answered Nov 02 '22 09:11

dev7