Skip to content

Commit

Permalink
Add timeout option (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
fregante authored and sindresorhus committed May 28, 2019
1 parent 08fc8ec commit 5bd3ad4
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 7 deletions.
7 changes: 7 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
17 changes: 10 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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});

Expand Down
7 changes: 7 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`<br>
Default: `Infinity`

Milliseconds to wait before stopping the search and resolving the promise to `undefined`.

### elementReadyPromise#stop()

Type: `Function`
Expand Down
30 changes: 30 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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});

Expand Down

0 comments on commit 5bd3ad4

Please sign in to comment.