@@ -8,7 +8,7 @@ import { ILogger, LogLevel } from "./ILogger";
8
8
import { IRetryPolicy } from "./IRetryPolicy" ;
9
9
import { IStreamResult } from "./Stream" ;
10
10
import { Subject } from "./Subject" ;
11
- import { Arg , getErrorString } from "./Utils" ;
11
+ import { Arg , getErrorString , Platform } from "./Utils" ;
12
12
13
13
const DEFAULT_TIMEOUT_IN_MS : number = 30 * 1000 ;
14
14
const DEFAULT_PING_INTERVAL_IN_MS : number = 15 * 1000 ;
@@ -49,6 +49,7 @@ export class HubConnection {
49
49
private _handshakeResolver ! : ( value ?: PromiseLike < { } > ) => void ;
50
50
private _handshakeRejecter ! : ( reason ?: any ) => void ;
51
51
private _stopDuringStartError ?: Error ;
52
+ private _lockResolver ! : ( value ?: PromiseLike < { } > ) => void ;
52
53
53
54
private _connectionState : HubConnectionState ;
54
55
// connectionStarted is tracked independently from connectionState, so we can check if the
@@ -65,6 +66,11 @@ export class HubConnection {
65
66
private _timeoutHandle ?: any ;
66
67
private _pingServerHandle ?: any ;
67
68
69
+ private _freezeEventListener = ( ) =>
70
+ {
71
+ this . _logger . log ( LogLevel . Warning , "The page is being frozen, this will likely lead to the connection being closed and messages being lost." ) ;
72
+ } ;
73
+
68
74
/** The server timeout in milliseconds.
69
75
*
70
76
* If this timeout elapses without receiving any messages from the server, the connection will be terminated with an error.
@@ -174,6 +180,27 @@ export class HubConnection {
174
180
try {
175
181
await this . _startInternal ( ) ;
176
182
183
+ if ( Platform . isBrowser ) {
184
+ if ( document ) {
185
+ document . addEventListener ( "freeze" , this . _freezeEventListener ) ;
186
+ }
187
+
188
+ const promise = new Promise ( ( res ) => {
189
+ this . _lockResolver = res ;
190
+ } ) ;
191
+
192
+ // Chrome and Edge currently support Web Locks, it's also experimental, so let's be safe and check if the APIs exist
193
+ // https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API
194
+ // This should prevent the browsers from sleeping the tab which would close the connection unexpectedly
195
+ if ( navigator && ( navigator as any ) . locks && ( navigator as any ) . locks . request ) {
196
+ // Use a 'shared' lock so multiple tabs to the same site can used the same lock
197
+ ( navigator as any ) . locks . request ( 'signalr_client_lock' , { mode : "shared" } , ( ) => {
198
+ // Keep lock until promise is resolved
199
+ return promise ;
200
+ } ) ;
201
+ }
202
+ }
203
+
177
204
this . _connectionState = HubConnectionState . Connected ;
178
205
this . _connectionStarted = true ;
179
206
this . _logger . log ( LogLevel . Debug , "HubConnection connected successfully." ) ;
@@ -721,6 +748,13 @@ export class HubConnection {
721
748
this . _connectionState = HubConnectionState . Disconnected ;
722
749
this . _connectionStarted = false ;
723
750
751
+ this . _lockResolver ( ) ;
752
+ if ( Platform . isBrowser ) {
753
+ if ( document ) {
754
+ document . removeEventListener ( "freeze" , this . _freezeEventListener ) ;
755
+ }
756
+ }
757
+
724
758
try {
725
759
this . _closedCallbacks . forEach ( ( c ) => c . apply ( this , [ error ] ) ) ;
726
760
} catch ( e ) {
0 commit comments