Last active
November 30, 2020 18:14
-
-
Save Xotabu4/b62a56e2183cc4c00cfe8b33bcfcc8dc to your computer and use it in GitHub Desktop.
Implementation of wait with return of last condition result
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
} | |
}) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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