Skip to content

Commit 245c412

Browse files
committed
refactor(WebSocketSubject): no longer relies on ReplaySubject.
1 parent 989c187 commit 245c412

File tree

1 file changed

+53
-45
lines changed

1 file changed

+53
-45
lines changed

packages/rxjs/src/internal/observable/dom/WebSocketSubject.ts

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Subject } from '../../Subject.js';
22
import { Subscriber, Observable, Subscription, operate } from '../../Observable.js';
3-
import { ReplaySubject } from '../../ReplaySubject.js';
4-
import { Observer, NextObserver } from '../../types.js';
3+
import { NextObserver } from '../../types.js';
54

65
/**
76
* WebSocketSubjectConfig is a plain Object that allows us to make our
@@ -158,7 +157,13 @@ export class WebSocketSubject<T> extends Subject<T> {
158157

159158
private _socket: WebSocket | null = null;
160159

161-
private _input: Observer<T>;
160+
private _inputBuffer: T[] = [];
161+
162+
private _hasError = false;
163+
164+
private _error: any;
165+
166+
private _isComplete = false;
162167

163168
constructor(urlConfigOrSource: string | WebSocketSubjectConfig<T>) {
164169
super();
@@ -177,13 +182,15 @@ export class WebSocketSubject<T> extends Subject<T> {
177182
}
178183

179184
this._output = new Subject<T>();
180-
this._input = new ReplaySubject();
181185
}
182186

183187
private _resetState() {
184188
this._socket = null;
185-
this._input = new ReplaySubject();
186189
this._output = new Subject<T>();
190+
this._inputBuffer = [];
191+
this._hasError = false;
192+
this._isComplete = false;
193+
this._error = null;
187194
}
188195

189196
/**
@@ -250,44 +257,14 @@ export class WebSocketSubject<T> extends Subject<T> {
250257

251258
this._config.openObserver?.next(evt);
252259

253-
const previousInput = this._input;
254-
255-
// We switch over now to passthrough all messages directly to the
256-
// to the socket, where previously we were queuing them up with
257-
// a ReplaySubject.
258-
this._input = new Subscriber<T>({
259-
next: (x) => {
260-
if (socket!.readyState === 1) {
261-
try {
262-
socket!.send(this._config.serializer!(x));
263-
} catch (e) {
264-
this._input.error(e);
265-
}
266-
}
267-
},
268-
error: (err: any) => {
269-
this._config.closingObserver?.next(undefined);
270-
if (err?.code) {
271-
socket!.close(err.code, err.reason);
272-
} else {
273-
_output.error(new TypeError(WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT));
274-
}
275-
this._resetState();
276-
},
277-
complete: () => {
278-
this._config.closingObserver?.next(undefined);
279-
socket!.close();
280-
this._resetState();
281-
},
282-
});
260+
while (this._inputBuffer.length > 0) {
261+
this.next(this._inputBuffer.shift()!);
262+
}
283263

284-
// If the _input was a ReplaySubject before, when we
285-
// subscribe right now, it will synchronously emit all
286-
// of the buffered values.
287-
if (previousInput instanceof ReplaySubject) {
288-
// Note that since `_input` is a `Subscriber`, this will
289-
// automatically wire up the subscription.
290-
previousInput.subscribe(this._input);
264+
if (this._hasError) {
265+
this.error(this._error);
266+
} else if (this._isComplete) {
267+
this.complete();
291268
}
292269
};
293270

@@ -322,15 +299,46 @@ export class WebSocketSubject<T> extends Subject<T> {
322299
}
323300

324301
next(value: T) {
325-
this._input.next(value);
302+
if (this._socket?.readyState !== 1) {
303+
this._inputBuffer.push(value);
304+
} else {
305+
try {
306+
this._socket.send(this._config.serializer!(value));
307+
} catch (err: any) {
308+
this._config.closingObserver?.next(undefined);
309+
if (err?.code) {
310+
this._socket.close(err.code, err.reason);
311+
} else {
312+
this._output.error(new TypeError(WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT));
313+
}
314+
this._resetState();
315+
}
316+
}
326317
}
327318

328319
error(err: any) {
329-
this._input.error(err);
320+
if (this._socket?.readyState === 1) {
321+
this._config.closingObserver?.next(undefined);
322+
if (err?.code) {
323+
this._socket?.close(err.code, err.reason);
324+
} else {
325+
this._output.error(new TypeError(WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT));
326+
}
327+
this._resetState();
328+
} else {
329+
this._hasError = true;
330+
this._error = err;
331+
}
330332
}
331333

332334
complete() {
333-
this._input.complete();
335+
if (this._socket?.readyState === 1) {
336+
this._config.closingObserver?.next(undefined);
337+
this._socket.close();
338+
this._resetState();
339+
} else {
340+
this._isComplete = true;
341+
}
334342
}
335343

336344
/** @internal */

0 commit comments

Comments
 (0)