Skip to content

Instantly share code, notes, and snippets.

@Xotabu4
Last active November 30, 2020 18:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xotabu4/b62a56e2183cc4c00cfe8b33bcfcc8dc to your computer and use it in GitHub Desktop.
Save Xotabu4/b62a56e2183cc4c00cfe8b33bcfcc8dc to your computer and use it in GitHub Desktop.
Implementation of wait with return of last condition result
// This waiters helps to solve issue when you need to wait for some results, but also want to get it:
const lastRes = await waitFor({
predicate: async () => {
const resp = await http.get('http://test.com/api/users')
return users.length > 0
}
})
const res = await http.get('http://test.com/api/users')
// Oops, need to make extra HTTP call! Not optimal!
// With this waiter you can get last result like this:
const lastRes = await waitForResult({
predicate: async () => {
const resp = await http.get('http://test.com/api/users')
return {
bool: users.length > 0
lastResult: resp.body
}
}
})
// Or, if you don't care about result, call waitFor:
const lastRes = await waitFor({
predicate: async () => {
const resp = await http.get('http://test.com/api/users')
return users.length > 0
}
})
type OptionsPart = {
timeoutMs?: number,
poolIntervalMs?: number,
errorMessage?: string,
falsyError?: boolean
}
export async function waitForResult<T>(options: {
predicate: () => Promise<{ bool: boolean, lastResult: T }>,
} & OptionsPart): Promise<T> {
const defaultOptions = {
timeoutMs: 5000,
poolIntervalMs: 100,
falsyError: false,
}
const opts = {
...defaultOptions,
...options
}
opts.errorMessage ?? `waitFor timed out after ${opts.timeoutMs}ms, condition function: ${opts.predicate}`;
const timeoutDeadline = new Date().getTime() + opts.timeoutMs;
let iterationRes: { bool: boolean, lastResult: T };
do {
if (new Date().getTime() > timeoutDeadline) {
throw new Error(opts.errorMessage)
}
const res = opts.predicate()
if (opts.falsyError) {
res.catch(err => false)
}
iterationRes = await res
if (!iterationRes.bool) {
await new Promise(resolve => setTimeout(resolve, opts.poolIntervalMs))
}
} while (!iterationRes.bool)
return iterationRes.lastResult
}
export async function waitFor(options: {
predicate: () => Promise<boolean>
} & OptionsPart): Promise<void> {
await waitForResult({
...options,
predicate: async () => {
return {
bool: await options.predicate(),
lastResult: null
}
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment