Use `MutationObserver` for a more efficient and modern approach to detect changes in the DOM and wait for elements to exist, as it avoids continuous polling and is generally more performant than `setInterval`.
Always clear your intervals with `clearInterval()` or disconnect your observers with `me.disconnect()` to prevent memory leaks and ensure that the JavaScript engine does not continue to check for the element after it has been found.
When using `setInterval`, choose an appropriate polling interval to balance responsiveness with performance; too frequent checks can lead to higher CPU usage and potential jank in your application.
Consider the scope of what you need to observe with `MutationObserver` and set the `childList` and `subtree` options accordingly to watch for changes in specific parts of the DOM tree, optimizing the observer's performance and resource usage.
// Method 1: Using setInterval
function waitForElement(selector, callback) {
var interval = setInterval(function() {
if (document.querySelector(selector)) {
clearInterval(interval);
callback();
}
}, 100); // Check every 100ms
}
waitForElement('#example-element', function() {
console.log('Element is now available.');
});
// Method 2: Using MutationObserver
function waitForElementObserver(selector, callback) {
var observer = new MutationObserver(function(mutations, me) {
var element = document.querySelector(selector);
if (element) {
callback(element);
me.disconnect(); // Stop observing
}
});
observer.observe(document, {
childList: true,
subtree: true
});
}
waitForElementObserver('#example-element', function(elem) {
console.log('Element is now available.');
});Forgetting to call clearInterval() with setInterval can cause memory leaks and degrade performance over time.
Using a polling interval that is too short with setInterval can lead to high CPU usage and application jank.
Not properly disconnecting a MutationObserver can result in resource overuse and potential memory leaks.
Misconfiguring MutationObserver options (e.g., watching too broad a subtree) can unnecessarily monitor irrelevant parts of the DOM, impacting performance.
// Inorrect: No clearInterval, can lead to memory leaks and unnecessary processing
function waitForElementBad(selector, callback) {
var interval = setInterval(function() {
if (document.querySelector(selector)) {
callback();
}
}, 100);
}
// Correct: Properly clearing interval after element is found
function waitForElementGood(selector, callback) {
var interval = setInterval(function() {
if (document.querySelector(selector)) {
clearInterval(interval);
callback();
}
}, 100);
}
// Inorrect: MutationObserver without disconnect leads to potential performance issues
function waitForElementObserverBad(selector, callback) {
var observer = new MutationObserver(function(mutations, me) {
if (document.querySelector(selector)) {
callback();
}
});
observer.observe(document, { childList: true, subtree: true });
}
// Correct: Disconnecting observer after element is found
function waitForElementObserverGood(selector, callback) {
var observer = new MutationObserver(function(mutations, me) {
var element = document.querySelector(selector);
if (element) {
callback(element);
me.disconnect();
}
});
observer.observe(document, { childList: true, subtree: true });
}
// Inorrect: Too frequent polling can affect performance
setInterval(function() {
if (document.querySelector('#someElement')) {
console.log('Element found!');
}
}, 10); // Checking every 10ms is generally excessive
// Correct: Reasonable polling interval
setInterval(function() {
if (document.querySelector('#someElement')) {
console.log('Element found!');
}
}, 100); // 100ms is a more balanced interval
// Inorrect: Observing unnecessary deep DOM changes
var observer = new MutationObserver(function() {
// Callback logic here
});
observer.observe(document, { childList: true, subtree: true });
// Correct: Limiting observation scope when possible
var observer = new MutationObserver(function() {
// Callback logic here
});
observer.observe(document.getElementById('specificContainer'), { childList: true, subtree: false });

Augustas Pelakauskas
2025-10-16


Yelyzaveta Hayrapetyan
2025-10-01

Get the latest news from data gathering world
Scale up your business with Oxylabs®
Proxies
Advanced proxy solutions
Data Collection
Datasets
Resources
Innovation hub