diff --git a/index.d.ts b/index.d.ts index a3803c8..1bf93ec 100644 --- a/index.d.ts +++ b/index.d.ts @@ -9,6 +9,13 @@ declare namespace elementReady { */ readonly target?: Element | Document; + /** + Milliseconds to wait before stopping the search and resolving the promise to `undefined`. + + @default Infinity + */ + readonly timeout?: number + /** Automatically stop checking for the element to be ready after the DOM ready event. The promise is then resolved to `undefined`. diff --git a/index.js b/index.js index 6af40b3..f0e31ad 100644 --- a/index.js +++ b/index.js @@ -5,13 +5,12 @@ const pDefer = require('p-defer'); const cache = new ManyKeysMap(); -const elementReady = (selector, options = {}) => { - const { - target = document, - stopOnDomReady = true - } = options; - - const cacheKeys = [target, selector, stopOnDomReady]; +const elementReady = (selector, { + target = document, + stopOnDomReady = true, + timeout = Infinity +} = {}) => { + const cacheKeys = [target, selector, stopOnDomReady, timeout]; const cachedPromise = cache.get(cacheKeys); if (cachedPromise) { return cachedPromise; @@ -36,6 +35,10 @@ const elementReady = (selector, options = {}) => { })(); } + if (timeout !== Infinity) { + setTimeout(stop, timeout); + } + // Interval to keep checking for it to come into the DOM (function check() { const element = target.querySelector(selector); diff --git a/index.test-d.ts b/index.test-d.ts index b7d5e1b..09e54ee 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -4,6 +4,7 @@ import elementReady = require('.'); const promise = elementReady('#unicorn'); elementReady('#unicorn', {target: document}); elementReady('#unicorn', {target: document.documentElement}); +elementReady('#unicorn', {timeout: 1000000}); elementReady('#unicorn', {stopOnDomReady: false}); diff --git a/readme.md b/readme.md index 8736fa5..ef782ad 100644 --- a/readme.md +++ b/readme.md @@ -54,6 +54,13 @@ Default: `true` Automatically stop checking for the element to be ready after the [DOM ready event](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event). The promise is then resolved to `undefined`. +##### timeout + +Type: `number`
+Default: `Infinity` + +Milliseconds to wait before stopping the search and resolving the promise to `undefined`. + ### elementReadyPromise#stop() Type: `Function` diff --git a/test.js b/test.js index 7af57da..5234b34 100644 --- a/test.js +++ b/test.js @@ -103,6 +103,36 @@ test('check if element ready before dom loaded', async t => { t.is(await elementCheck, element); }); +test('check if element ready after timeout', async t => { + const elementCheck = elementReady('#cheezburger', { + stopOnDomReady: false, + timeout: 1000 + }); + + // The element will be added eventually, but we're not around to wait for it + setTimeout(() => { + const element = document.createElement('p'); + element.id = 'cheezburger'; + document.body.append(element); + }, 50000); + + const element = await elementCheck; + t.is(element, undefined); +}); + +test('check if element ready before timeout', async t => { + const element = document.createElement('p'); + element.id = 'thunders'; + document.body.append(element); + + const elementCheck = elementReady('#thunders', { + stopOnDomReady: false, + timeout: 10 + }); + + t.is(await elementCheck, element); +}); + test('ensure only one promise is returned on multiple calls passing the same selector', t => { const elementCheck = elementReady('#not-found', {stopOnDomReady: false});