skip to Main Content

I have an external asynchronous script needs to finish executing before the page loads. To my understanding (from this thread), the default behaviour before the page starts to load is that it finishes rendering the head tag’s contents, and if it includes a script, it finishes parsing that too, before proceeding to load the page. However, I could be wrong, but this seems to not apply to asynchronous scripts.

How could I make this example asynchronous script below finish executing (and all promises finishing) before the page starts to load?

The page, including the script:

Playground: https://playcode.io/1782092

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>p {color: blue}</style>

    <script>
  // Function to create a fake promise that resolves after 3 seconds
  async function fakePromise() {
    return new Promise(function(resolve, reject) {
      setTimeout(resolve, 3000); // Resolve after 3 seconds
    });
  }

  // Use async/await to wait for the fake promise to resolve
  async function applyStyle() {
    await fakePromise();

    // Create a <style> element
    var styleElement = document.createElement('style');

    // Define the CSS rule
    var css = "p { color: pink !important; }";

    // Add the CSS rule to the <style> element
    styleElement.appendChild(document.createTextNode(css));

    // Insert the <style> element into the <head> of the document
    document.head.insertBefore(styleElement, document.head.firstChild);
  }

  // Call the function to apply the style
  applyStyle();

  // *** in the REAL app, this script would just have empty contents and have a src attribute ***
</script>

  </head>
  <body>
    
    <p>testing</p>

  </body>
</html>

As you can see, the example ‘testing’ text changes colour after 3 seconds, but the problem is that this happens after the page has loaded. The blue ‘testing’ text should never appear, because the promise wouldn’t have resolved by then, and when it is resolved, it changes to pink, hence you should only see pink text.

If this is not possible, how else could I, for example, redirect to another page after the asynchronous script finishes but before the page starts to load?

2

Answers


  1. <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>p {color: white}</style>
    
        <script>
          // Function to create a fake promise that resolves after 3 seconds
          async function fakePromise() {
            return new Promise(function(resolve, reject) {
              setTimeout(resolve, 6000); // Resolve after 3 seconds
            });
          }
    
          // Use async/await to wait for the fake promise to resolve
          async function applyStyle() {
            await fakePromise();
            
            // Create a <style> element
            var styleElement = document.createElement('style');
            
            // Define the CSS rule
            var css = "p { color: pink !important; }";
            
            // Add the CSS rule to the <style> element
            styleElement.appendChild(document.createTextNode(css));
            
            // Insert the <style> element into the <head> of the document
            document.head.insertBefore(styleElement, document.head.firstChild);
          }
    
          // Wait for the "load" event to fire before calling applyStyle
          window.addEventListener("load", function(event) {
            applyStyle();
          });
    
    // Wait for the "load" event to fire before calling applyStyle and redirecting
    window.addEventListener("load", function(event) {
      applyStyle();
      // Redirect to another page
      window.location.href = "https://example.com/your_redirect_Page_here";
    });
    
        </script>
      </head>
      <body>
        <p>testing</p>
      </body>
    </html>
    Login or Signup to reply.
  2. I am not sure if this will be helpful for your purpose. But, here you go.

    So, I have set the body display to none till the fakePromise() resolves. Once the promise resolves, the body is displayed with all the changes incorporated.

    https://playcode.io/1784955

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>p {color: blue}</style>
    
        <script>
      // Function to create a fake promise that resolves after 3 seconds
      async function fakePromise() {
        return new Promise(function(resolve, reject) {
          setTimeout(resolve, 3000); // Resolve after 3 seconds
        });
      }
    
      // Use async/await to wait for the fake promise to resolve
      async function applyStyle() {
        await fakePromise();
    
        // Create a <style> element
        var styleElement = document.createElement('style');
    
        // Define the CSS rule
        var css = "p { color: pink !important; }";
    
        // Add the CSS rule to the <style> element
        styleElement.appendChild(document.createTextNode(css));
    
        // Insert the <style> element into the <head> of the document
        document.head.insertBefore(styleElement, document.head.firstChild);
    var x = document.getElementsByTagName("BODY")[0];
    x.style.display= null;
    
      }
    
      // Call the function to apply the style
      applyStyle();
    
      // *** in the REAL app, this script would just have empty contents and have a src attribute ***
    </script>
    
      </head>
      <body style="display:none;">
        <p>testing</p>
    
      </body>
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search