Skip to content

Instantly share code, notes, and snippets.

@robertpitt
Last active January 15, 2020 00:49
Show Gist options
  • Save robertpitt/cce38ec3996dc545b1c511f43864616b to your computer and use it in GitHub Desktop.
Save robertpitt/cce38ec3996dc545b1c511f43864616b to your computer and use it in GitHub Desktop.
/**
* Perform a async sleep operation, this is useful for testing
*/
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))
/**
* Debounce a async function call
*/
const debounce = (fn, offsetMs = 0) => {
let timer = null
let resolves = []
return (...props) => {
// If the function is called multiple times this clear timeout will
// reset the execution offset
clearTimeout(timer)
// We create a timer to execute the function at the offset
timer = setTimeout(() => {
// As the timeout called this callback, we can actually execute the request
const targetPromiseResult = fn.call(this, ...props)
// EHandle the resolvers
resolves.forEach(resolver => resolver(targetPromiseResult))
resolves = []
}, offsetMs)
return new Promise((resolve, reject) => resolves.push(resolve))
}
}
/**
* Based on David Walsh's "JavaScript fetch with Timeout"
* @see {@link https://davidwalsh.name/fetch-timeout}
*
* @param {() => Promise} fn
* @param {number} [timeout]
*
* @returns {Promise}
*/
const callWithTimeout = (fn, timeout) => {
let didTimeOut = false
return new Promise((resolve, reject) => {
const timer =
timeout &&
setTimeout(() => {
didTimeOut = true
reject(new Error('Request timed out'))
}, timeout)
fn()
.then(response => {
// Clear the timeout as cleanup
clearTimeout(timer)
if (!didTimeOut) {
resolve(response)
}
})
.catch(err => {
// Rejection already happened with setTimeout
if (didTimeOut) return
// Reject with error
reject(err)
})
})
}
/**
* Poll a Promiser Factory
* @param {object} options An options object
* @param {() => Promise} options.fn A promise
* @param {number} options.interval Time in ms representing the time span between the promise resolving and the next one firing
* @param {number} options.timeout The maximum amount of time in ms which the promise is allowed to take
* @param {(value: any) => any} options.onSuccess The success callback
* @param {(reason: any) => any} options.onError The error callback
*
* @returns {{start: () => void, stop: () => void}}
*/
const pollable = ({ fn, interval, timeout, onSuccess, onError }) => {
let running = false
return {
/**
* Starts the interval
*/
start: () => {
running = true;
(function run () {
callWithTimeout(fn, timeout)
.then(res => {
if (running) {
onSuccess(res)
sleep(interval).then(run)
}
})
.catch(err => {
if (running) {
onError(err)
sleep(interval).then(run)
}
})
})()
},
/**
* Stops the interval
*/
stop: () => {
running = false
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment