Skip to content

Commit

Permalink
fix(store): complete dispatched$ in internal actions
Browse files Browse the repository at this point in the history
We complete the `dispatched$` subject within the internal actions once the application is destroyed
to ensure there are no active subscribers after resources have been cleaned up.
  • Loading branch information
arturovt committed Dec 23, 2024
1 parent 12393de commit dbec7c6
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $ npm install @ngxs/store@dev
- Fix(store): Add root store initializer guard [#2278](https://github.com/ngxs/store/pull/2278)
- Fix(store): Reduce change detection cycles with pending tasks [#2280](https://github.com/ngxs/store/pull/2280)
- Fix(store): Complete action results on destroy [#2282](https://github.com/ngxs/store/pull/2282)
- Fix(store): Complete `dispatched$` in internal actions [#2285](https://github.com/ngxs/store/pull/2285)
- Refactor(form-plugin): Replace `takeUntil` with `takeUntilDestroyed` [#2283](https://github.com/ngxs/store/pull/2283)

### 19.0.0 2024-12-3
Expand Down
18 changes: 10 additions & 8 deletions packages/store/src/actions-stream.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { inject, Injectable, OnDestroy } from '@angular/core';
import { DestroyRef, inject, Injectable } from '@angular/core';
import { ɵOrderedSubject } from '@ngxs/store/internals';
import { Observable, Subject, filter, share } from 'rxjs';

Expand All @@ -25,7 +25,7 @@ export interface ActionContext<T = any> {
* Internal Action stream that is emitted anytime an action is dispatched.
*/
@Injectable({ providedIn: 'root' })
export class InternalActions extends ɵOrderedSubject<ActionContext> implements OnDestroy {
export class InternalActions extends ɵOrderedSubject<ActionContext> {
// This subject will be the first to know about the dispatched action, its purpose is for
// any logic that must be executed before action handlers are invoked (i.e., cancelation).
readonly dispatched$ = new Subject<ActionContext>();
Expand All @@ -36,13 +36,15 @@ export class InternalActions extends ɵOrderedSubject<ActionContext> implements
this.pipe(filter(ctx => ctx.status === ActionStatus.Dispatched)).subscribe(ctx => {
this.dispatched$.next(ctx);
});
}

ngOnDestroy(): void {
// Complete the subject once the root injector is destroyed to ensure
// there are no active subscribers that would receive events or perform
// any actions after the application is destroyed.
this.complete();
const destroyRef = inject(DestroyRef);
destroyRef.onDestroy(() => {
// Complete the subject once the root injector is destroyed to ensure
// there are no active subscribers that would receive events or perform
// any actions after the application is destroyed.
this.complete();
this.dispatched$.complete();
});
}
}

Expand Down

0 comments on commit dbec7c6

Please sign in to comment.