Waiting For Elements To Exist In The Dom With User-specified Attempts

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.