@iam4x/reconnecting-websocket 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -34,6 +34,7 @@ export declare class ReconnectingWebSocket {
34
34
  constructor(url: string, options?: ReconnectOptions);
35
35
  connect(): void;
36
36
  emit(event: EventType, payload: any): void;
37
+ private runWithFinalizer;
37
38
  scheduleReconnect(): void;
38
39
  startHealthCheck(): void;
39
40
  stopHealthCheck(): void;
package/dist/index.js CHANGED
@@ -82,18 +82,21 @@ export class ReconnectingWebSocket {
82
82
  this.openFn = (event) => {
83
83
  // Only process if event is from the current socket
84
84
  if (event.target === currentWs && this.ws === currentWs) {
85
+ const isReconnect = this.wasConnected;
85
86
  this.clearTimers();
86
87
  this.retryCount = 0;
87
- this.emit("open", event);
88
- // Emit reconnect event if this was a reconnection after a disconnection
89
- if (this.wasConnected) {
90
- this.emit("reconnect", event);
91
- }
92
88
  this.wasConnected = true;
93
89
  this.startHealthCheck();
94
90
  this.startInactivityTimer();
95
- // Flush any queued messages now that socket is open
96
- this.flushMessageQueue();
91
+ this.runWithFinalizer(() => {
92
+ this.emit("open", event);
93
+ if (isReconnect) {
94
+ this.emit("reconnect", event);
95
+ }
96
+ }, () => {
97
+ // Flush queued messages even if a listener throws during open/reconnect.
98
+ this.flushMessageQueue();
99
+ });
97
100
  }
98
101
  };
99
102
  this.msgFn = (event) => {
@@ -106,12 +109,16 @@ export class ReconnectingWebSocket {
106
109
  this.closeFn = (event) => {
107
110
  // Only process if event is from the current socket
108
111
  if (event.target === currentWs && this.ws === currentWs) {
112
+ const shouldReconnect = !this.forcedClose;
109
113
  this.stopHealthCheck();
110
114
  this.stopInactivityTimer();
111
- this.emit("close", { code: event.code, reason: event.reason });
112
- if (!this.forcedClose) {
113
- this.scheduleReconnect();
114
- }
115
+ this.runWithFinalizer(() => {
116
+ this.emit("close", { code: event.code, reason: event.reason });
117
+ }, () => {
118
+ if (shouldReconnect) {
119
+ this.scheduleReconnect();
120
+ }
121
+ });
115
122
  }
116
123
  };
117
124
  this.errorFn = (event) => {
@@ -131,6 +138,33 @@ export class ReconnectingWebSocket {
131
138
  listener(payload);
132
139
  }
133
140
  }
141
+ runWithFinalizer(action, finalizer) {
142
+ let didThrow = false;
143
+ let thrown;
144
+ try {
145
+ action();
146
+ }
147
+ catch (error) {
148
+ didThrow = true;
149
+ thrown = error;
150
+ }
151
+ finally {
152
+ if (finalizer) {
153
+ try {
154
+ finalizer();
155
+ }
156
+ catch (error) {
157
+ if (!didThrow) {
158
+ didThrow = true;
159
+ thrown = error;
160
+ }
161
+ }
162
+ }
163
+ }
164
+ if (didThrow) {
165
+ throw thrown;
166
+ }
167
+ }
134
168
  scheduleReconnect() {
135
169
  // Clear any existing reconnect timeout first to prevent multiple reconnects
136
170
  if (this.reconnectTimeout) {
@@ -180,6 +214,7 @@ export class ReconnectingWebSocket {
180
214
  if (this.forcedClose) {
181
215
  return;
182
216
  }
217
+ const shouldReconnect = !this.forcedClose;
183
218
  // Proactively trigger reconnection due to inactivity
184
219
  // Don't rely on the close event as it may never fire on a stalled connection
185
220
  if (this.ws) {
@@ -198,10 +233,15 @@ export class ReconnectingWebSocket {
198
233
  this.ws.close();
199
234
  // Clear the socket reference
200
235
  this.ws = undefined;
201
- // Emit close event to listeners with a special code indicating inactivity timeout
202
- this.emit("close", { code: 4000, reason: "Inactivity timeout" });
203
- // Schedule reconnection directly without waiting for close event
204
- this.scheduleReconnect();
236
+ this.runWithFinalizer(() => {
237
+ // Emit close event to listeners with a special code indicating inactivity timeout.
238
+ this.emit("close", { code: 4000, reason: "Inactivity timeout" });
239
+ }, () => {
240
+ if (shouldReconnect) {
241
+ // Schedule reconnection directly without waiting for close event.
242
+ this.scheduleReconnect();
243
+ }
244
+ });
205
245
  }
206
246
  }, this.options.watchingInactivityTimeout);
207
247
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "module": "src/index.ts",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
- "version": "1.4.0",
6
+ "version": "1.4.1",
7
7
  "private": false,
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {