You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
1.7 KiB
66 lines
1.7 KiB
// @flow
|
|
// small utilities for Promises
|
|
|
|
import logger from 'logger'
|
|
|
|
export const delay = (ms: number): Promise<void> => new Promise(f => setTimeout(f, ms))
|
|
|
|
const defaults = {
|
|
maxRetry: 4,
|
|
interval: 300,
|
|
intervalMultiplicator: 1.5,
|
|
}
|
|
export function retry<A>(f: () => Promise<A>, options?: $Shape<typeof defaults>): Promise<A> {
|
|
const { maxRetry, interval, intervalMultiplicator } = { ...defaults, ...options }
|
|
|
|
return rec(maxRetry, interval)
|
|
|
|
function rec(remainingTry, interval) {
|
|
const result = f()
|
|
if (remainingTry <= 0) {
|
|
return result
|
|
}
|
|
// In case of failure, wait the interval, retry the action
|
|
return result.catch(e => {
|
|
logger.warn('retry failed', e.message)
|
|
return delay(interval).then(() => rec(remainingTry - 1, interval * intervalMultiplicator))
|
|
})
|
|
}
|
|
}
|
|
|
|
export function idleCallback() {
|
|
return new Promise(resolve => window.requestIdleCallback(resolve))
|
|
}
|
|
|
|
type CancellablePollingOpts = {
|
|
pollingInterval?: number,
|
|
shouldThrow?: Error => boolean,
|
|
}
|
|
|
|
export function createCancelablePolling(
|
|
job: any => Promise<any>,
|
|
{ pollingInterval = 500, shouldThrow }: CancellablePollingOpts = {},
|
|
) {
|
|
let isUnsub = false
|
|
const unsubscribe = () => (isUnsub = true)
|
|
const getUnsub = () => isUnsub
|
|
const promise = new Promise((resolve, reject) => {
|
|
async function poll() {
|
|
try {
|
|
const res = await job()
|
|
if (getUnsub()) return
|
|
resolve(res)
|
|
} catch (err) {
|
|
if (shouldThrow && shouldThrow(err)) {
|
|
reject(err)
|
|
return
|
|
}
|
|
await delay(pollingInterval)
|
|
if (getUnsub()) return
|
|
poll()
|
|
}
|
|
}
|
|
poll()
|
|
})
|
|
return { unsubscribe, promise }
|
|
}
|
|
|