Skip to content

Commit

Permalink
perf(asyncThrottle): Improve performance (#7224)
Browse files Browse the repository at this point in the history
Co-authored-by: Dominik Dorfmeister <office@dorfmeister.cc>
  • Loading branch information
webNeat and TkDodo committed Apr 8, 2024
1 parent e03cc3a commit 39909c4
Showing 1 changed file with 24 additions and 37 deletions.
61 changes: 24 additions & 37 deletions packages/query-async-storage-persister/src/asyncThrottle.ts
Expand Up @@ -11,46 +11,33 @@ export function asyncThrottle<TArgs extends ReadonlyArray<unknown>>(
) {
if (typeof func !== 'function') throw new Error('argument is not function.')

let running = false
let lastTime = 0
let timeout: ReturnType<typeof setTimeout>
let currentArgs: TArgs | null = null
let nextExecutionTime = 0
let lastArgs = null
let isExecuting = false
let isScheduled = false

const execFunc = async () => {
if (currentArgs) {
const args = currentArgs
currentArgs = null
return async (...args: TArgs) => {
lastArgs = args
if (isScheduled) return
isScheduled = true
while (isExecuting) {
await new Promise((done) => setTimeout(done, interval))
}
while (Date.now() < nextExecutionTime) {
await new Promise((done) =>
setTimeout(done, nextExecutionTime - Date.now()),
)
}
isScheduled = false
isExecuting = true
try {
await func(...lastArgs)
} catch (error) {
try {
running = true
await func(...args)
} catch (error) {
onError(error)
} finally {
lastTime = Date.now() // this line must after 'func' executed to avoid two 'func' running in concurrent.
running = false
}
}
}

const delayFunc = async () => {
clearTimeout(timeout)
timeout = setTimeout(() => {
if (running) {
delayFunc() // Will come here when 'func' execution time is greater than the interval.
} else {
execFunc()
}
}, interval)
}

return (...args: TArgs) => {
currentArgs = args

const tooSoon = Date.now() - lastTime < interval
if (running || tooSoon) {
delayFunc()
} else {
execFunc()
} catch {}
}
nextExecutionTime = Date.now() + interval
isExecuting = false
}
}

0 comments on commit 39909c4

Please sign in to comment.