On this page
A keyboard placed on a white surface, accompanied by text that includes "JAVASCRIPT Wait for the DOM element."

JavaScript and wait until DOM element exists

Performance-friendly way to wait until DOM element exists in JavaScript.

To wait for an HTML element to exist in the DOM using JavaScript, we’ll use requestAnimationFrame to periodically check for the element’s existence, and combine it with Promise to achieve this without blocking the main thread.

This approach is performance-friendly because requestAnimationFrame allows the browser to optimize rendering and ensures that the checks occur at the right time in the rendering cycle.

Introduction

Waiting for an HTML element to exist is a common problem in JavaScript development for several reasons:

  1. Dynamic content: dynamic web content is loaded in stages, often after the initial page load or in response to specific user actions. If you try to access these elements before they’re loaded, you’ll encounter errors because they haven’t been added to the DOM (Document Object Model).
  2. Page loading sequence: the page loading sequence can be complex, with multiple scripts and stylesheets being loaded in a specific order. This can lead to situations where elements are not yet available in the DOM when the code tries to access them.
  3. Third-party libraries and frameworks: many third-party libraries and frameworks, such as React, Angular, or Vue.js, use dynamic rendering and asynchronous loading techniques, which can make it challenging to access DOM elements at the right time.

The below waitUntilElementIsRendered function provides a simple and efficient way to wait for a DOM element to exist, making it easier to handle complex scenarios.

How to wait until a DOM element exists before executing a JavaScript function?

There are several ways, like using the method setTimeout or MutationObserver, to wait until a DOM element exists before executing a JavaScript function.

However, we are going to use requestAnimationFrame and Promise as it only checks for the element on the next animation frame, it’s easy to use with async/await syntax and it doesn’t require manually clearing intervals or disconnecting Mutation observers.

Solution and implementation

The following implementation is intended for use in a browser environment, where the DOM is available.

The function waitUntilElementIsRendered is:

  1. Efficient: requestAnimationFrame ensures that the checking function runs in sync with the browser’s rendering cycle, which can help reduce CPU usage and improve performance when specifically compared to using setInterval or setTimeout methods. This is particularly important in scenarios where the DOM may be updated frequently.
  2. Non-blocking: by using Promise, you can create asynchronous code that waits for an element to exist without blocking the main thread, allowing for more efficient and responsive execution.
  3. Simple: the code is relatively simple and easy to understand, making it easier to maintain and debug.
  4. Flexible for the element identifier: the function argument elementOrSelector can either be a string representing a CSS selector or a direct reference to a DOM element. This flexibility allows the function to be used in various contexts.
  5. Managing timeout: this approach allows you to use a timeout, which can prevent the function from running indefinitely. This is crucial for preventing potential hangs in applications where elements may not load as expected. If the timeout is exceeded, it resolves the Promise with null.
JavaScript and wait until DOM element exists
/**
 * Waits for an element to be rendered in the DOM.
 *
 * @param {string|HTMLElement} elementOrSelector - The element or selector to wait for.
 * @param {number} [timeout=10000] - The timeout in milliseconds.
 * @returns {Promise<HTMLElement|null>} A Promise that resolves with the element or null if the timeout is reached.
 */

function waitUntilElementIsRendered(elementOrSelector, timeout) {
  timeout = typeof timeout === "number" ? timeout : 10000;

  const waitForElement = (resolve) => {
    const startTime = window.performance.now();

    const checkElement = () => {
      const currentTime = window.performance.now();

      if (currentTime - startTime >= timeout) {
        resolve(null);

        return;
      }

      const element = typeof elementOrSelector === "string" ? document.querySelector(elementOrSelector) : elementOrSelector;

      if (element) {
        resolve(element);

        return;
      }

      window.requestAnimationFrame(checkElement);
    };

    window.requestAnimationFrame(checkElement);
  };

  return new Promise(waitForElement);
}

The window.performance object is used here to measure time intervals. Specifically, window.performance.now() is used to get the current time in milliseconds.

The reason for using window.performance.now() instead of the standard Date.now() or new Date().getTime() is that performance.now() provides a higher resolution timer, which is more suitable for measuring small time intervals, such as those used in animations and performance-critical code.

Workable example

Related posts

Comments

Leave a Reply

Search in sitelint.com

Audit and debug pages with browser extension

Boost your website’s quality by auditing your page with SiteLint, a chromium-based extension that improves accessibility, quality, technical SEO, and provides easy-to-understand reports to help you prioritize and fix issues.