Last active
September 18, 2016 05:56
-
-
Save nbish11/f26221d83f1713622d598a8bfda983ef to your computer and use it in GitHub Desktop.
Promise based DOM poller.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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