I'm using Angular 18 with TanStack Angular Query and have a question about handling observables in the queryFn.
In my queryFn, I'm using lastValueFrom() with an HTTP request like this:
queryFn: () => {
return lastValueFrom(this.#http.get<Array<string>>('/api/tasks'));
}
My Question:
Since lastValueFrom automatically unsubscribes once it emits a value, do I need to explicitly add .pipe(takeUntilDestroyed()) or any other cleanup logic for proper resource management?
Additionally, does Angular Query automatically cancel in-flight requests if the component is destroyed or the query is invalidated?
I want to ensure I'm following best practices for both Angular and TanStack Angular Query. Any insights would be greatly appreciated!
I'm using Angular 18 with TanStack Angular Query and have a question about handling observables in the queryFn.
In my queryFn, I'm using lastValueFrom() with an HTTP request like this:
queryFn: () => {
return lastValueFrom(this.#http.get<Array<string>>('/api/tasks'));
}
My Question:
Since lastValueFrom automatically unsubscribes once it emits a value, do I need to explicitly add .pipe(takeUntilDestroyed()) or any other cleanup logic for proper resource management?
Additionally, does Angular Query automatically cancel in-flight requests if the component is destroyed or the query is invalidated?
I want to ensure I'm following best practices for both Angular and TanStack Angular Query. Any insights would be greatly appreciated!
Share Improve this question edited Mar 20 at 13:58 Naren Murali 60.4k5 gold badges44 silver badges78 bronze badges asked Mar 19 at 23:08 Eternal SunshineEternal Sunshine 951 silver badge7 bronze badges1 Answer
Reset to default 1Looking at the documentation, I can find the DestroyRef
being used to complete the stream, so .pipe(takeUntilDestroyed())
is not needed.
create-base-query.ts
effect(() => {
// observer.trackResult is not used as this optimization is not needed for Angular
const observer = observerSignal()
untracked(() => {
const unsubscribe = ngZone.runOutsideAngular(() =>
observer.subscribe(
notifyManager.batchCalls((state) => {
ngZone.run(() => {
...
...
}),
),
)
destroyRef.onDestroy(unsubscribe)
Looks like the previous in-flight requests are not cancelled by injectQuery
, I searched for a possible workaround, but did not find any.
export class SimpleExampleComponent {
readonly #http = inject(HttpClient);
readonly query = injectQuery(() => ({
queryKey: ['repoData'],
queryFn: ({ signal }) =>
lastValueFrom(
this.#http.get<Response>('https://api.github/repos/tanstack/query')
),
}));
reload() {
this.query.refetch();
}
}
Set network to 3G
and click the refresh button and see the output in network tab.
Stackblitz Demo
Due to availability of signal
property, we can use it with fetch API
to achieve this behavior.
readonly query = injectQuery(() => ({
queryKey: ['repoData'],
queryFn: ({ signal }) =>
fetch('https://api.github/repos/tanstack/query', {
signal: signal,
}).then((x) => x.json()),
}));