Skip to content

Commit

Permalink
fix(websocket-plugin): do not dispatch action when root injector is d…
Browse files Browse the repository at this point in the history
…estroyed

Prevents dispatching `WebSocketDisconnected` action in `ngOnDestroy` hook of the `WebSocketHandler`.
The `ngOnDestroy` hook is called after root injector has been destroyed, meaning that no dispatch
stuff should be done.
  • Loading branch information
arturovt committed Nov 17, 2024
1 parent aa4dd85 commit 4aab4ac
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 11 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ $ npm install @ngxs/store@dev

### To become next patch version

- ...
- Fix(websocket-plugin): Do not dispatch action when root injector is destroyed [#2257](https://github.com/ngxs/store/pull/2257)

### 18.1.5 2024-11-12

Expand Down
16 changes: 8 additions & 8 deletions packages/websocket-plugin/src/websocket-handler.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Injectable, Inject, OnDestroy, NgZone } from '@angular/core';
import { Injectable, Inject, NgZone, inject, DestroyRef } from '@angular/core';
import { Actions, Store, ofActionDispatched } from '@ngxs/store';
import { getValue } from '@ngxs/store/plugins';
import { ReplaySubject, Subject, fromEvent } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ReplaySubject, Subject, fromEvent, takeUntil } from 'rxjs';

import {
ConnectWebSocket,
Expand All @@ -18,7 +17,7 @@ import {
} from './symbols';

@Injectable({ providedIn: 'root' })
export class WebSocketHandler implements OnDestroy {
export class WebSocketHandler {
private _socket: WebSocket | null = null;

private readonly _socketClosed$ = new Subject<void>();
Expand All @@ -34,11 +33,12 @@ export class WebSocketHandler implements OnDestroy {
@Inject(NGXS_WEBSOCKET_OPTIONS) private _options: NgxsWebSocketPluginOptions
) {
this._setupActionsListeners();
}

ngOnDestroy(): void {
this._disconnect(/* forcelyCloseSocket */ true);
this._destroy$.next();
const destroyRef = inject(DestroyRef);
destroyRef.onDestroy(() => {
this._closeConnection(/* forcelyCloseSocket */ true);
this._destroy$.next();
});
}

private _setupActionsListeners(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@ describe('WebSocketHandler cleanup', () => {
);
const store = ngModuleRef.injector.get(Store);
const webSocketHandler = ngModuleRef.injector.get(WebSocketHandler);
const ngOnDestroySpy = jest.spyOn(webSocketHandler, 'ngOnDestroy');
const nextSpy = jest.fn();
webSocketHandler['_destroy$'].subscribe(nextSpy);

store.dispatch(new ConnectWebSocket());

server.on('connection', () => {
server.on('close', () => {
try {
// Assert
expect(ngOnDestroySpy).toHaveBeenCalled();
expect(nextSpy).toHaveBeenCalled();
} finally {
server.stop(done);
}
Expand Down

0 comments on commit 4aab4ac

Please sign in to comment.