Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timeout option #21

Merged
merged 8 commits into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 false
*/
readonly timeout?: number | false
fregante marked this conversation as resolved.
Show resolved Hide resolved

/**
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 = 0
} = {}) => {
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 > 0) {
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 | false`<br>
Default: `false`

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