Skip to content

Instantly share code, notes, and snippets.

@srph
Created January 11, 2023 13:02
Show Gist options
  • Save srph/0fe1f219da9c6086a6575db3f4f9b5ee to your computer and use it in GitHub Desktop.
Save srph/0fe1f219da9c6086a6575db3f4f9b5ee to your computer and use it in GitHub Desktop.
JS: Poll until condition is true (with max attempts and manual abort)
@@ -0,0 +1,44 @@
import { delay } from '../time'
type PollValueCallback<T> = () => Promise<T>
type PollConditionCallback<T> = (t: T) => boolean
interface PollOptions {
ms?: number
max?: number
signal?: AbortSignal
}
// Repetitively run an async function (like requesting data) until its condition succeeds.
// A good sample use-case would be checking that a transaction status changed.
// This is not the function to repetitively load data in attempt to update it every x seconds.
//
// It's very important that you either use the built-in max attempt options
// or provide an AbortController so you are able to opt out of the function.
// Otherwise, this function may run forever, and you might not know it - that's not very good.
//
// We have no strong opinions regarding throwing a function.
// It's wise to silence the errors yourself for now if you want to keep running the poll
// function even if the async function (like requestingng data) fails.
export async function poll<T = unknown>(
callback: PollValueCallback<T>,
condition: PollConditionCallback<T>,
{ ms = Infinity, max = Infinity, signal }: PollOptions
): Promise<T | undefined> {
for (let attempts = 0; attempts < max; attempts++) {
if (signal?.aborted) {
return undefined
}
const value = await callback()
if (condition(value) === true) {
return value
}
await delay(ms)
}
return undefined
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment