• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mobxjs / mobx / 3919621547

pending completion
3919621547

push

github

Jan Plaček
Merge branch 'registry-refactor' of github.com:mobxjs/mobx into registry-refactor

1666 of 2056 branches covered (81.03%)

3215 of 3503 relevant lines covered (91.78%)

6477.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.49
/packages/mobx/src/api/when.ts
1
import {
47✔
2
    $mobx,
3
    IReactionDisposer,
4
    Lambda,
5
    autorun,
6
    createAction,
7
    getNextId,
8
    die,
9
    allowStateChanges
10
} from "../internal"
11

12
// https://github.com/mobxjs/mobx/issues/3582
13
interface GenericAbortSignal {
14
    readonly aborted: boolean
15
    onabort?: ((...args: any) => any) | null
16
    addEventListener?: (...args: any) => any
17
    removeEventListener?: (...args: any) => any
18
}
19

20
export interface IWhenOptions {
21
    name?: string
22
    timeout?: number
23
    onError?: (error: any) => void
24
    signal?: GenericAbortSignal
25
}
26

27
export function when(
28
    predicate: () => boolean,
29
    opts?: IWhenOptions
30
): Promise<void> & { cancel(): void }
31
export function when(
32
    predicate: () => boolean,
33
    effect: Lambda,
34
    opts?: IWhenOptions
35
): IReactionDisposer
36
export function when(predicate: any, arg1?: any, arg2?: any): any {
47✔
37
    if (arguments.length === 1 || (arg1 && typeof arg1 === "object")) {
43✔
38
        return whenPromise(predicate, arg1)
15✔
39
    }
40
    return _when(predicate, arg1, arg2 || {})
28✔
41
}
42

43
function _when(predicate: () => boolean, effect: Lambda, opts: IWhenOptions): IReactionDisposer {
44
    let timeoutHandle: any
45
    if (typeof opts.timeout === "number") {
43✔
46
        const error = new Error("WHEN_TIMEOUT")
7✔
47
        timeoutHandle = setTimeout(() => {
7✔
48
            if (!disposer[$mobx].isDisposed_) {
3✔
49
                disposer()
2✔
50
                if (opts.onError) {
2!
51
                    opts.onError(error)
2✔
52
                } else {
53
                    throw error
×
54
                }
55
            }
56
        }, opts.timeout)
57
    }
58

59
    opts.name = __DEV__ ? opts.name || "When@" + getNextId() : "When"
43!
60
    const effectAction = createAction(
43✔
61
        __DEV__ ? opts.name + "-effect" : "When-effect",
43!
62
        effect as Function
63
    )
64
    // eslint-disable-next-line
65
    var disposer = autorun(r => {
43✔
66
        // predicate should not change state
67
        let cond = allowStateChanges(false, predicate)
63✔
68
        if (cond) {
62✔
69
            r.dispose()
36✔
70
            if (timeoutHandle) {
36✔
71
                clearTimeout(timeoutHandle)
3✔
72
            }
73
            effectAction()
36✔
74
        }
75
    }, opts)
76
    return disposer
43✔
77
}
78

79
function whenPromise(
80
    predicate: () => boolean,
81
    opts?: IWhenOptions
82
): Promise<void> & { cancel(): void } {
83
    if (__DEV__ && opts && opts.onError) {
15!
84
        return die(`the options 'onError' and 'promise' cannot be combined`)
×
85
    }
86
    if (opts?.signal?.aborted) {
15!
87
        return Object.assign(Promise.reject(new Error("WHEN_ABORTED")), { cancel: () => null })
×
88
    }
89
    let cancel
90
    let abort
91
    const res = new Promise((resolve, reject) => {
15✔
92
        let disposer = _when(predicate, resolve as Lambda, { ...opts, onError: reject })
15✔
93
        cancel = () => {
15✔
94
            disposer()
3✔
95
            reject(new Error("WHEN_CANCELLED"))
3✔
96
        }
97
        abort = () => {
15✔
98
            disposer()
1✔
99
            reject(new Error("WHEN_ABORTED"))
1✔
100
        }
101
        opts?.signal?.addEventListener?.("abort", abort)
15✔
102
    }).finally(() => opts?.signal?.removeEventListener?.("abort", abort))
15✔
103
    ;(res as any).cancel = cancel
15✔
104
    return res as any
15✔
105
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc