Skip to content

fix(common): abort HTTP requests once application is destroyed #59575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

arturovt
Copy link
Contributor

In this commit, we abort any pending HTTP requests when the application is destroyed to prevent memory leaks and the execution of operations that should not occur once resources are released. For example, if an HTTP response is returned after the application is destroyed and someone calls runInInjectionContext, it would throw an error indicating that the injector has already been destroyed. This ensures a graceful cleanup, ensuring that no requests proceed once the root injector is destroyed.

@angular-robot angular-robot bot added the area: common Issues related to APIs in the @angular/common package label Jan 16, 2025
@ngbot ngbot bot added this to the Backlog milestone Jan 16, 2025
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 0d2ee56 to c6662f0 Compare January 17, 2025 07:46
@arturovt arturovt marked this pull request as ready for review January 17, 2025 07:47
@pullapprove pullapprove bot requested a review from thePunderWoman January 17, 2025 07:47
Copy link
Contributor

@thePunderWoman thePunderWoman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Can you add some tests?

@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from c6662f0 to 2d176f6 Compare January 17, 2025 21:37
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch 3 times, most recently from cdc5b27 to be512d3 Compare January 25, 2025 20:21
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from be512d3 to 230ea2c Compare January 27, 2025 19:15
Copy link
Contributor

@thePunderWoman thePunderWoman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for adding the test!

@pullapprove pullapprove bot requested a review from alxhub January 27, 2025 21:19
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 230ea2c to 31ad250 Compare January 27, 2025 21:25
@arturovt
Copy link
Contributor Author

@AndrewKushnir updated the nit comment.

@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 31ad250 to 315d577 Compare January 30, 2025 20:01
@AndrewKushnir AndrewKushnir requested a review from kirjs February 11, 2025 04:47
@kirjs kirjs added the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label Feb 19, 2025
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 315d577 to 92932e7 Compare February 20, 2025 21:30
@pullapprove pullapprove bot requested a review from kirjs February 21, 2025 19:50
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 92932e7 to 1a934fe Compare February 22, 2025 17:01
@e-oz
Copy link

e-oz commented Feb 24, 2025

@krivanek06 worth checking if it will be a breaking change for the service you described in your article "Simple User Event Tracker".

@kirjs kirjs modified the milestones: Backlog, v20 candidates Mar 11, 2025
@kirjs kirjs added action: discuss and removed action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews labels Mar 11, 2025
@alxhub alxhub removed this from the v20 candidates milestone Apr 24, 2025
@ngbot ngbot bot added this to the Backlog milestone Apr 24, 2025
@alxhub
Copy link
Member

alxhub commented May 22, 2025

Hey @arturovt,

I think this fix is in the right spirit - cancelling outstanding work on destruction makes sense. But I suspect it should be implemented differently.

Right now, this cancels at the backend, and specifically aborts the fetch() request only. As I understand, this doesn't impact the behavior of XHR-based applications. It also doesn't tear down the Observable subscription, so consumers receive AbortErrors. If an interceptor is handling the request independently of the backend (caching, local storage, websocket, etc) it'd be unaware of the cancellation.

Instead, we should cancel requests at the frontend of HttpClient. If we add takeUntilDestroy() or similar behavior to HttpClient.request() itself, then it will trigger the backend unsubscription logic, plus correctly inform interceptors of unsubscription, plus not propagate spurious AbortErrors. That'd be a much more correct solution.

It should then be straightforward to test that an ongoing request is cancelled when the HttpClient-containing injector is destroyed.

What do you think?

@arturovt
Copy link
Contributor Author

@alxhub your comments make sense. Before we move forward — just out of curiosity — should we still care about XHR-based applications? @JeanMeche has a PR where fetch will be used by default, with XHR as a fallback.

@JeanMeche
Copy link
Member

We haven't decided yet if we should change the default backend. We should still assume XHR is the default.

@JeanMeche
Copy link
Member

@arturovt Do you still intend to apply the suggested changes ?

@arturovt
Copy link
Contributor Author

arturovt commented Jun 5, 2025

Yes, I'll proceed with the proposed implementation.

@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 1a934fe to 0ab9a86 Compare June 5, 2025 11:40
@arturovt arturovt marked this pull request as draft June 5, 2025 11:41
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 0ab9a86 to e9a0c27 Compare June 5, 2025 11:46
Comment on lines 125 to 139
// Attempt to retrieve a `DestroyRef` optionally.
// For backwards compatibility reasons, this cannot be required.
if (isInInjectionContext()) {
inject(DestroyRef, {optional: true})?.onDestroy(() => this.destroyed$.next());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed the unfortunate reality we're in.
I would suggest that we log a warning if the HttpClient wasn't created in an injection context (which it arguable should) and that cleanup won't be ensured.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch 2 times, most recently from 7cf3bcc to 09afa1d Compare June 5, 2025 13:13
@JeanMeche JeanMeche marked this pull request as ready for review June 5, 2025 13:15
In this commit, we abort any pending HTTP requests when the application is destroyed to prevent memory leaks and the execution of operations that should not occur once resources are released. For example, if an HTTP response is returned after the application is destroyed and someone calls `runInInjectionContext`, it would throw an error indicating that the injector has already been destroyed. This ensures a graceful cleanup, ensuring that no requests proceed once the root injector is destroyed.
@arturovt arturovt force-pushed the fix/common-fetch-abort-requests-after-destroy branch from 09afa1d to 2e8acd1 Compare June 5, 2025 13:37
@thePunderWoman thePunderWoman added action: review The PR is still awaiting reviews from at least one requested reviewer and removed action: discuss labels Jun 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action: review The PR is still awaiting reviews from at least one requested reviewer area: common Issues related to APIs in the @angular/common package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants