Skip to content

Commit f058823

Browse files
committed
implement cleanup function for async computed signal
1 parent 15c178b commit f058823

File tree

3 files changed

+16
-6
lines changed

3 files changed

+16
-6
lines changed

packages/qwik/src/core/reactive-primitives/impl/async-computed-signal-impl.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { qwikDebugToString } from '../../debug';
33
import type { Container } from '../../shared/types';
44
import { ChoreType } from '../../shared/util-chore-type';
55
import { isPromise } from '../../shared/utils/promises';
6-
import { trackFn } from '../../use/utils/tracker';
6+
import { cleanupFn, trackFn } from '../../use/utils/tracker';
77
import type { BackRef } from '../cleanup';
88
import type { AsyncComputeQRL, EffectSubscription } from '../types';
99
import { _EFFECT_BACK_REF, EffectProperty, SignalFlags } from '../types';
1010
import { throwIfQRLNotResolved } from '../utils';
1111
import { ComputedSignalImpl } from './computed-signal-impl';
1212
import { setupSignalValueAccess } from './signal-impl';
13+
import type { NoSerialize } from '../../shared/utils/serialize-utils';
1314

1415
const DEBUG = false;
1516
const log = (...args: any[]) =>
@@ -32,6 +33,7 @@ export class AsyncComputedSignalImpl<T>
3233

3334
$pendingEffects$: null | Set<EffectSubscription> = null;
3435
$failedEffects$: null | Set<EffectSubscription> = null;
36+
$destroy$: NoSerialize<() => void> | null;
3537
private $promiseValue$: T | null = null;
3638

3739
[_EFFECT_BACK_REF]: Map<EffectProperty | string, EffectSubscription> | null = null;
@@ -103,8 +105,13 @@ export class AsyncComputedSignalImpl<T>
103105
const computeQrl = this.$computeQrl$;
104106
throwIfQRLNotResolved(computeQrl);
105107

108+
const [cleanup] = cleanupFn(this, (err) => this.$container$?.handleError(err, null!));
106109
const untrackedValue =
107-
this.$promiseValue$ ?? (computeQrl.getFn()({ track: trackFn(this, this.$container$) }) as T);
110+
this.$promiseValue$ ??
111+
(computeQrl.getFn()({
112+
track: trackFn(this, this.$container$),
113+
cleanup,
114+
}) as T);
108115
if (isPromise(untrackedValue)) {
109116
this.untrackedPending = true;
110117
this.untrackedFailed = false;

packages/qwik/src/core/reactive-primitives/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export interface InternalSignal<T = any> extends InternalReadonlySignal<T> {
3838
export type ComputeQRL<T> = QRLInternal<ComputedFn<T>>;
3939
export type AsyncComputedCtx = {
4040
track: Tracker;
41+
cleanup: (callback: () => void) => void;
4142
};
4243
export type AsyncComputeQRL<T> = QRLInternal<AsyncComputedFn<T>>;
4344

packages/qwik/src/core/use/utils/tracker.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import { EffectProperty, STORE_ALL_PROPS, type Consumer } from '../../reactive-p
1010
import { isSignal } from '../../reactive-primitives/utils';
1111
import { qError, QError } from '../../shared/error/error';
1212
import type { Container } from '../../shared/types';
13-
import { noSerialize } from '../../shared/utils/serialize-utils';
13+
import { noSerialize, type NoSerialize } from '../../shared/utils/serialize-utils';
1414
import { isFunction, isObject } from '../../shared/utils/types';
1515
import { invoke, newInvokeContext } from '../use-core';
16-
import type { Task, Tracker } from '../use-task';
16+
import type { Tracker } from '../use-task';
17+
18+
export type Destroyable = { $destroy$: NoSerialize<() => void> | null };
1719

1820
export const trackFn =
1921
(target: Consumer, container: Container | null): Tracker =>
@@ -44,8 +46,8 @@ export const trackFn =
4446
});
4547
};
4648

47-
export const cleanupFn = (
48-
target: Task,
49+
export const cleanupFn = <T extends Destroyable>(
50+
target: T,
4951
handleError: (err: unknown) => void
5052
): [(callback: () => void) => void, (() => void)[]] => {
5153
let cleanupFns: (() => void)[] | null = null;

0 commit comments

Comments
 (0)