Jack Jack - 2 months ago 6
jQuery Question

jQuery's function $(function())’s execute order when the $(function()) called more one times

Code like this:



$(window.document).ready(function () {
window.alert('alert 1');
});

$(function () {
window.alert('alert 2');
});

$(function () {
window.alert('alert 3');
});

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo2</title>
<script src="jquery-3.1.1.js"></script>
<script src="demo2.js"></script>
</head>
<body>

</body>
</html>





when i execute the above code, the page' alert order sometimes is:
alert 1, alert 2, alert 3, and sometimes is: alert 1, alert 3, alert 2.
could anyone tell my why?

Answer

At lines 3930 through 3947 jQuery version 3.1.1 handles .ready() being called after document has already loaded. At line 3938 jQuery.ready is called inside of setTimeout without a duration set with attached comment

// Handle it asynchronously to allow scripts the opportunity to delay ready

which would explain how window.alert('alert 3') could potentially be called before window.alert('alert 2')


// Catch cases where $(document).ready() is called
// after the browser event has already occurred.
// Support: IE <=9 - 10 only
// Older IE sometimes signals "interactive" too soon
if ( document.readyState === "complete" ||
    ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

    // Handle it asynchronously to allow scripts the opportunity to delay ready
    window.setTimeout( jQuery.ready ); // Line 3938

} else {

    // Use the handy event callback
    document.addEventListener( "DOMContentLoaded", completed );

    // A fallback to window.onload, that will always work
    window.addEventListener( "load", completed );
}

The following stacksnippet should reproduce result described by OP

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Demo2</title>
    <script src="https://code.jquery.com/jquery-3.1.1.js"></script>
    <script>
      $(window.document).ready(function () {
    window.alert('alert 1');
});

$(function () {
    window.alert('alert 2');
});

$(function () {
   window.alert('alert 3');
});
    </script>
</head>
<body>

</body>
</html>

See also completed function at Line 3924

// The ready event handler and self cleanup method
function completed() {
    document.removeEventListener( "DOMContentLoaded", completed );
    window.removeEventListener( "load", completed );
    jQuery.ready();
}

See plnkr http://plnkr.co/edit/C0leBhYJq8CMh7WqndzH?p=preview at version 1


Edit, Updated

To ensure the order of execution of functions at .ready() you can return a promise from the function calls, use .then() inside single .ready() call to call functions defined globally or previously within .ready() handler.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Demo2</title>
  <script src="https://code.jquery.com/jquery-3.1.1.js"></script>
  <script>
    function ready1(wait, index) {
      // do stuff
      return new Promise(resolve => {
          setTimeout(() => {
            window.alert('alert ' + index);
            resolve(index)
          })
        })
        .then((i) => console.log(i))
    }

    function ready2(wait, index) {
      // do stuff
      return new Promise(resolve => {
          setTimeout(() => {
            window.alert('alert ' + index);
            resolve(index)
          })
        })
        .then((i) => console.log(i))
    }

    function ready3(wait, index) {
      // do stuff
      return new Promise(resolve => {
          setTimeout(() => {
            window.alert('alert' + index);
            resolve(index)
          })
        })
        .then((i) => console.log(i))
    }
    $().ready(function() {
      ready1(3000, 0) // 3000ms timeout
      .then(function() {
        return ready2(1500, 1) // 1500ms timeout
      })
      .then(function() {
        return ready3(750, 2) // 750ms timeout
      });
    })
  </script>
</head>

</html>

plnkr http://plnkr.co/edit/C0leBhYJq8CMh7WqndzH?p=preview at version 4