I had to implement some testing logic recently where I wanted to wait for a heavy page to load and for specific elements to become available. I knew I wanted a function that polled the page and returned true
if it found the element or rejected if it didn’t.
I actually looked some a pre existing solution and turned up a blank. There are code examples out there, but some developers have created some over engineered solutions using things like proxies, mutation observers and other convoluted ways of waiting for elements.
All I wanted to be able to do was call a function which would wait for an element to exist in the page and return true if it was found or error out if it wasn’t.
async function waitForElement(selector: string, attempts: number = 10) { const query = document.querySelectorAll(selector); if (query.length) { return true; } setTimeout(() => { attempts--; if (attempts > 0) { return waitForElement(selector, attempts); } throw new Error('Element not found'); }, 100); }
This code is written with TypeScript and is quite easy to follow. We create a new asynchronous function which will return a promise. It accepts a selector which gets passed to querySelectorall
and a second argument which is the number of attempts before it errors out.
The function recursively calls itself until the number of attempts equals 0 and then it throws an error, thus, rejecting the promise. If it finds the element, it returns true.
const elementFound = await waitForElement('#someelement');
Sure, some of the other solutions out there might be more technically impressive, but I’m a realist and more often than not, I go for the solutions that are readable and functional.