Skip to content

Instantly share code, notes, and snippets.

@nbish11
Last active September 18, 2016 05:56
Show Gist options
  • Save nbish11/f26221d83f1713622d598a8bfda983ef to your computer and use it in GitHub Desktop.
Save nbish11/f26221d83f1713622d598a8bfda983ef to your computer and use it in GitHub Desktop.
Promise based DOM poller.
/**
* Poll the DOM until a condition has been met, or a timeout occurs.
* @copyright 2016 Nathan Bishop
* @license MIT http://choosealicense.com/licenses/mit/
* @param {Number} timeout How long to poll the dom for, in milliseconds.
* @param {Function} condition The condition to test for. Must return a boolean.
* @return {Promise} A `Promise` object.
*/
function pollDom(timeout, condition) {
var expiry = Date.now() + Number(timeout);
return new Promise(function (resolve, reject) {
(function poll() {
// If the condition was met, we're done!
if (condition()) {
resolve();
// If the condition wasn't met and the timeout hasn't elapsed, try again.
} else if (Date.now() < expiry) {
setTimeout(poll, 100);
// Condition wasn't matched and too much time elapsed, reject!
} else {
reject(new Error('Element could not be found in DOM before timeout occurred.'));
}
})();
});
}
// Usage:
pollDom(2000, function () {
return Boolean(document.getElementById('test'));
})
.then(function () {
console.log('success');
})
.catch(function (e) {
console.log(e.message);
});
// -------------------------------------------------------------------------------
/**
* Poll the DOM until a condition has been met, or a timeout occurs.
* @copyright 2016 Nathan Bishop
* @license MIT http://choosealicense.com/licenses/mit/
* @class Poller
* @param {Function} condition The condition to test for. Must return a boolean.
* @return {Promise} A `Promise` object.
*/
function Poller(condition) {
if (!(this instanceof Poller)) {
throw new TypeError('Cannot call a class as a function');
}
// By providing a context you can do some pretty awesome stuff
// in your condition function, in addtion to setting poller options.
const context = { timeout: 2000, interval: 100 };
const expiry = Date.now();
return new Promise(function (resolve, reject) {
(function poll() {
// If the condition was met, we're done!
if (condition.call(context)) {
resolve();
// If the condition wasn't met and the timeout hasn't elapsed, try again.
} else if (Date.now() < (expiry + context.timeout)) {
setTimeout(poll, context.interval);
// Condition wasn't matched and too much time elapsed, reject!
} else {
reject(new Error('Element could not be found in DOM before timeout occurred.'));
}
})();
});
}
/**
* Static method to create new `Poller` instances.
* @param {Function} condition The condition to test for. Must return a boolean.
* @return {Poller} A new `Poller` instance.
*/
Poller.create = function (condition) {
return new Poller(condition);
};
// Usage:
Poller.create(function () {
this.timeout = 10000;
this.interval = 1000;
console.log(this);
return Boolean(document.getElementById('test'));
})
.then(function () {
console.log('success');
})
.catch(function (e) {
console.log(e.message);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment