Appearance
until
Promised one-time watch for changes
Demo
Usage
Wait for some async data to be ready
tsx
import { until } from '@reause/shared'
const isReady = { value: false }
// ... somewhere later: isReady.value = true
const ready = await until(() => isReady.value).toBe(true)Wait for custom conditions
tsx
import { until } from '@reause/shared'
const count = { value: 0 }
void until(() => count.value).toMatch(v => v > 7).then(() => {
alert('Count is now larger than 7!')
})
count.value = 8 // the next poll resolvesTimeout
tsx
// will resolve once the source reads `true` or after 1000ms
await until(() => isReady.value).toBe(true, { timeout: 1000 })
// will throw if timeout
try {
await until(() => isReady.value).toBe(true, { timeout: 1000, throwOnTimeout: true })
// isReady.value === true
}
catch (e) {
// timeout
}More Examples
tsx
await until(() => isReady.value).toBe(true)
await until(() => isReady.value).toBe(true, { timeout: 1000 })
await until(() => count.value).toMatch(v => v > 10 && v < 100)
await until(() => count.value).changed()
await until(() => count.value).changedTimes(10)
await until(() => count.value).toBeTruthy()
await until(() => count.value).toBeNull()
await until(() => count.value).not.toBeNull()
await until(() => count.value).not.toBeTruthy()Source
until(source) accepts a plain value or a zero-argument getter. The value argument of toBe(value) / toContains(value) is a plain value.
Caveat —
untilpolls the source it was given. A plain value is a snapshot and never changes between polls, so use a getter when the value can change afteruntilwas called. ARef/{ current }object is not accepted directly — pass() => ref.current. A source that is itself a function is treated as a getter and invoked.
Type Declarations
Toggle
ts
export interface UntilToMatchOptions {
timeout?: number;
throwOnTimeout?: boolean;
deep?: boolean;
}
export interface UntilBaseInstance<T, Not extends boolean = false> {
toMatch: (<U extends T = T>(condition: (v: T) => v is U, options?: UntilToMatchOptions) => Not extends true ? Promise<Exclude<T, U>> : Promise<U>) & ((condition: (v: T) => boolean, options?: UntilToMatchOptions) => Promise<T>);
changed: (options?: UntilToMatchOptions) => Promise<T>;
changedTimes: (n?: number, options?: UntilToMatchOptions) => Promise<T>;
}
export interface UntilValueInstance<T, Not extends boolean = false> extends UntilBaseInstance<T, Not> {
readonly not: UntilValueInstance<T, Not extends true ? false : true>;
toBe: <P = T>(value: P, options?: UntilToMatchOptions) => Not extends true ? Promise<T> : Promise<P>;
toBeTruthy: (options?: UntilToMatchOptions) => Not extends true ? Promise<T & Falsy> : Promise<Exclude<T, Falsy>>;
toBeNull: (options?: UntilToMatchOptions) => Not extends true ? Promise<Exclude<T, null>> : Promise<null>;
toBeUndefined: (options?: UntilToMatchOptions) => Not extends true ? Promise<Exclude<T, undefined>> : Promise<undefined>;
toBeNaN: (options?: UntilToMatchOptions) => Promise<T>;
}
export interface UntilArrayInstance<T> extends UntilBaseInstance<T> {
readonly not: UntilArrayInstance<T>;
toContains: (value: ElementOf<T>, options?: UntilToMatchOptions) => Promise<T>;
}
type Falsy = false | void | null | undefined | 0 | 0n | ''
type ElementOf<T> = T extends readonly unknown[] ? T[number] : never
export function until<T extends unknown[]>(r: () => T): UntilArrayInstance<T>
export function until<T>(r: () => T): UntilValueInstance<T>
export function until<T extends unknown[]>(r: T): UntilArrayInstance<T>
export function until<T>(r: T): UntilValueInstance<T>