33

I'm working on a codebase with multiple blocks of code setting some behavior on document.ready() (jQuery). Is there a way to enforce that one specific block is called before any of the others?

Background: I need to detect JS errors in an automated testing environment, so I need the code that starts logging JS errors to execute before any other JS code executes.

goat
  • 31,486
  • 7
  • 73
  • 96
ankit
  • 3,328
  • 3
  • 26
  • 39
  • 2
    Does the error logging code block really *need* to wait for the DOM to be ready? – Kevin B Jun 04 '12 at 15:26
  • @KevinB Great point! It may even be worthwhile for it not to wait... – msanford Jun 04 '12 at 15:27
  • @KevinB I'm not very familiar with JS. If I placed the code outside any block, would it be guaranteed to run before any other code was executed? – ankit Jun 04 '12 at 15:31
  • It runs exactly where you place it in your DOM. If it's the first script tag in your page (say at the top of your HTML `head`) it will run first. – Paul Jun 04 '12 at 15:32
  • @AnkitSoni providing that it is placed within the html tags and all other code blocks rely on DOMReady, it will run before any of the code within the DOMReady blocks. – Kevin B Jun 04 '12 at 15:33
  • @KevinB OK I just tested this, turns out I do need to wait for the DOM to be ready. Otherwise, the details of the error reported (Message,URL,linenumber) are undefined. – ankit Jun 04 '12 at 15:36

5 Answers5

28

document.ready() callbacks are called in the order they were registered. If you register your testing callback first, it will be called first.

Also if your testing code does not actually need to manipulate the DOM, then you may be able to run it as the code is parsed and not wait until the DOM is ready which would run before the other document.ready() callbacks get called. Or, perhaps you could run part of your testing code immediately and defer only the part that uses the DOM until document.ready().

Another idea is (for testing purposes only) you could run with a slightly modified version of jQuery that added a flag to document.ready() that when passed and set to true indicated to call that function first or you could add a new method document.readyFirst() that would call your function first. This would involve minor changes to the document.ready() processing code in jQuery.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
26

As @jfriend00 mention that ready callbacks are called in the order they were registered.

So even if this code block called on the beginning, you can set another callback in it so it'll be executed on endmost.

jQuery(document).ready(function(){
    jQuery(document).ready(function(){
        // This block will be executed after all ready calls.
    });
});
ecabuk
  • 1,641
  • 1
  • 18
  • 20
  • 1
    This method actually works, but I can imagine it giving some pretty weird results in some cases. Also, it has code smell all over it and it's pretty confusing for future devs maintaining the code. – Edwin Apr 13 '16 at 10:37
  • Can confirm it works but it sure feels weird. Can be very confusing if you have multiple calls that you want to order. – Sebastien Jul 15 '20 at 14:42
  • A brilliant and simple solution. – jmichas Feb 08 '22 at 23:37
7

You should be able to use holdReady to do this. As long as it is included before your ready events, you can run your own code and then trigger the other ready events.

jncraton
  • 9,022
  • 3
  • 34
  • 49
2

I was trying to do something similar, I was loading a bunch of polyfills that had .ready() functions, but I also had my own .ready()s on page that I needed executed first, though the polyfills were loaded in the header.

I found a nice way around it by having a .ready() very early on (right after jQuery loads) that executes functions from an array. Because it's very early in the source code it's .ready() is executed first. Further down the page I can add functions to the array and, so they all execute before any other .ready()s.

I've wrapped it up in a .beforeReady() function and put it on GitHub as jQuery-Before-Ready for anyone that is interested. https://github.com/aim12340/jQuery-Before-Ready

EamonnM
  • 2,201
  • 1
  • 13
  • 18
1

You can execute the logging start code in DOMReady and other initialization in load. Or you could make your own initialization manager which calls your logging start code first and then all other initialization callbacks (provided that those are registered with your manager and not jQuery, unless you want to hack jQuery and extract them from there, which I don't advise).

Mr. TA
  • 5,230
  • 1
  • 28
  • 35