@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 +1 -0
- package/dist/index.js +55 -15
- package/package.json +1 -1
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
|
-
|
|
96
|
-
|
|
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.
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
}
|