2022-03-01 12:11:56 +01:00
|
|
|
/**
|
|
|
|
* Utility to wrap an async function and ensure all invocations happen
|
|
|
|
* sequentially.
|
|
|
|
* @param fn the async function to run
|
|
|
|
* @return {Promise} a sequential version of the function
|
|
|
|
*/
|
|
|
|
export const sequential = fn => {
|
2022-07-14 17:17:25 +02:00
|
|
|
let queue = []
|
2022-10-20 17:03:53 +02:00
|
|
|
return (...params) => {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
queue.push(async () => {
|
|
|
|
let data, error
|
|
|
|
try {
|
|
|
|
data = await fn(...params)
|
|
|
|
} catch (err) {
|
|
|
|
error = err
|
|
|
|
}
|
|
|
|
queue.shift()
|
|
|
|
if (queue.length) {
|
|
|
|
queue[0]()
|
|
|
|
}
|
|
|
|
if (error) {
|
|
|
|
reject(error)
|
|
|
|
} else {
|
|
|
|
resolve(data)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
if (queue.length === 1) {
|
|
|
|
queue[0]()
|
2022-07-14 17:17:25 +02:00
|
|
|
}
|
|
|
|
})
|
2022-03-01 12:11:56 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-05 16:57:21 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Utility to debounce an async function and ensure a minimum delay between
|
|
|
|
* invocations is enforced.
|
|
|
|
* @param callback an async function to run
|
|
|
|
* @param minDelay the minimum delay between invocations
|
|
|
|
* @returns {Promise} a debounced version of the callback
|
|
|
|
*/
|
|
|
|
export const debounce = (callback, minDelay = 1000) => {
|
|
|
|
let timeout
|
|
|
|
return async (...params) => {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
if (timeout) {
|
|
|
|
clearTimeout(timeout)
|
|
|
|
}
|
|
|
|
timeout = setTimeout(async () => {
|
|
|
|
resolve(await callback(...params))
|
|
|
|
}, minDelay)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-10-08 16:03:44 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Utility to throttle invocations of a synchronous function. This is better
|
|
|
|
* than a simple debounce invocation for a number of reasons. Features include:
|
|
|
|
* - First invocation is immediate (no initial delay)
|
|
|
|
* - Every invocation has the latest params (no stale params)
|
|
|
|
* - There will always be a final invocation with the last params (no missing
|
|
|
|
* final update)
|
|
|
|
* @param callback
|
|
|
|
* @param minDelay
|
|
|
|
* @returns {Function} a throttled version function
|
|
|
|
*/
|
|
|
|
export const throttle = (callback, minDelay = 1000) => {
|
|
|
|
let lastParams
|
|
|
|
let stalled = false
|
|
|
|
let pending = false
|
|
|
|
const invoke = (...params) => {
|
|
|
|
lastParams = params
|
|
|
|
if (stalled) {
|
|
|
|
pending = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
callback(...lastParams)
|
|
|
|
stalled = true
|
|
|
|
setTimeout(() => {
|
|
|
|
stalled = false
|
|
|
|
if (pending) {
|
|
|
|
pending = false
|
|
|
|
invoke(...lastParams)
|
|
|
|
}
|
|
|
|
}, minDelay)
|
|
|
|
}
|
|
|
|
return invoke
|
|
|
|
}
|