idlize

Форк
0
173 строки · 6.6 Кб
1
/*
2
 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
15

16
import { __context, __id } from "../internals"
17
import { scheduleCallback } from "../states/GlobalStateManager"
18
import { ControlledScope, MutableState } from "../states/State"
19
import { functionOverValue } from "@koalaui/common"
20

21
/**
22
 * It calculates the value of the given lambda and caches its result.
23
 * In contrast to the `remember` function, the given lambda can be recalculated
24
 * if it uses values of states (including parameters of @memo-functions).
25
 * If the given lambda does not use any state, it will be calculated only once.
26
 *
27
 * @param compute - a function to compute cacheable result
28
 * @returns the last calculated value
29
 * @see remember
30
 * @experimental
31
 * @memo:intrinsic
32
 */
33
export function memo<Value>(compute: () => Value): Value {
34
    const scope = __context().scope<Value>(__id(), undefined, undefined, undefined, undefined, undefined)
35
    return scope.unchanged ? scope.cached : scope.recache(compute())
36
}
37

38
/**
39
 * It calculates the value of the given lambda and caches its result.
40
 * In contrast to the `memo` function, the given lambda is calculated only once
41
 * even if it uses values of states (including parameters of @memo-functions).
42
 *
43
 * @param compute - a function to compute cacheable result
44
 * @returns the last calculated value
45
 * @see memo
46
 * @memo:intrinsic
47
 */
48
export function remember<Value>(compute: () => Value): Value {
49
    const scope = __context().scope<Value>(__id(), 0, undefined, undefined, undefined, true) // do not recalculate if used states were updated
50
    return scope.unchanged ? scope.cached : scope.recache(compute())
51
}
52

53
/**
54
 * It calculates the value of the given lambda, caches its result,
55
 * and notifies, that this method is removed from the composition.
56
 *
57
 * @param compute - a function to compute cacheable result
58
 * @param cleanup - a function to cleanup computed result on dispose
59
 * @returns the last calculated value
60
 * @see remember
61
 * @memo:intrinsic
62
 */
63
export function rememberDisposable<Value>(compute: () => Value, cleanup: (value: Value|undefined) => void): Value {
64
    const scope = __context().scope<Value>(__id(), 0, undefined, undefined, cleanup, true) // do not recalculate if used states were updated
65
    return scope.unchanged ? scope.cached : scope.recache(compute())
66
}
67

68
/**
69
 * Creates remembered state which can be updated from anywhere,
70
 * and if changed - all depending memo functions recache automatically.
71
 * Note that you can specify the value directly for primitive values,
72
 * which do not require computations or memory allocation.
73
 * It is highly recommended to provide a lambda for all others values.
74
 *
75
 * @param initial - initial value supplier used on the state creation
76
 * @returns a state remembered for the current code position
77
 * @memo:intrinsic
78
 */
79
export function rememberMutableState<Value>(initial: (() => Value) | Value): MutableState<Value> {
80
    const scope = __context().scope<MutableState<Value>>(__id(), 0, undefined, undefined, undefined, true) // do not recalculate if used states were updated
81
    return scope.unchanged ? scope.cached : scope.recache(__context()
82
        .mutableState(
83
            functionOverValue<Value>(initial) ?
84
                (initial as (() => Value))() :
85
                (initial as Value),
86
            undefined, undefined, undefined
87
        )
88

89
    )
90
}
91

92
/**
93
 * Remember mutable state which is computed in async way and is undefined if promise
94
 * is not fulfilled.
95
 *
96
 * @param compute function returning promise to compute the state
97
 * @param initial value stored to the state
98
 * @param onError callback called if promise was rejected
99
 * @memo
100
 */
101
export function rememberMutableAsyncState<Value>(compute: () => Promise<Value | undefined>, initial?: Value, onError?: (e: Error) => void): MutableState<Value | undefined> {
102
    const result = rememberMutableState<Value | undefined>(initial)
103
    remember(() => {
104
        compute()
105
            .then((value) => result.value = value)
106
            .catch((error: Error) => {
107
                result.value = undefined
108
                onError?.(error)
109
            })
110
    })
111
    return result
112
}
113

114
/**
115
 * Remember mutable state which is
116
 * re-computed in async way if key has changed
117
 * and undefined while promise is not fulfilled.
118
 *
119
 * @param key a value to trigger state recomputation
120
 * @param compute function returning promise to compute the state
121
 * @param initial value stored to the state
122
 * @param onError callback called if promise was rejected
123
 * @memo
124
 */
125
export function rememberComputableState<Key, Value>(
126
    key: Key,
127
    /** @skip:memo */
128
    compute: (key: Key) => Promise<Value | undefined>,
129
    initial?: Value,
130
    onError?: (e: Error) => void
131
): MutableState<Value | undefined> {
132
    const result = rememberMutableState<Value | undefined>(initial)
133
    const keyLocal: Key = key // subscribe to a key changes
134
    scheduleCallback(() => ((key: Key) => {
135
        compute(key)
136
            .then((value: Value | undefined): Value | undefined => result.value = value)
137
            .catch((error: Error) => {
138
                result.value = undefined
139
                onError?.(error)
140
            })
141
    })(keyLocal))
142
    return result
143
}
144

145
/**
146
 * Remember a value which is
147
 * re-computed in async way if key has changed
148
 * and undefined while promise is not fulfilled.
149
 *
150
 * @param key a value to trigger state recomputation
151
 * @param compute function returning promise to compute the state
152
 * @param initial value stored to the state
153
 * @param onError callback called if promise was rejected
154
 * @memo
155
 */
156
export function rememberComputableValue<Key, Value>(
157
    key: Key,
158
    /** @skip:memo */
159
    compute: (key: Key) => Promise<Value | undefined>,
160
    initial?: Value,
161
    onError?: (e: Error) => void
162
): Value | undefined {
163
    return rememberComputableState(key, compute, initial, onError).value
164
}
165

166
/**
167
 * @param invalidate - callback that will be notified when any state is modified within the scope
168
 * @return a user-controlled scope which can be used outside of the incremental update
169
 * @memo:intrinsic
170
 */
171
export function rememberControlledScope(invalidate: () => void): ControlledScope {
172
    return __context().controlledScope(__id(), invalidate)
173
}
174

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.