@@ -55,6 +55,7 @@ export class HubConnection {
55
55
private _connectionStarted : boolean ;
56
56
private _startPromise ?: Promise < void > ;
57
57
private _stopPromise ?: Promise < void > ;
58
+ private _nextKeepAlive : number = 0 ;
58
59
59
60
// The type of these a) doesn't matter and b) varies when building in browser and node contexts
60
61
// Since we're building the WebPack bundle directly from the TypeScript, this matters (previously
@@ -74,6 +75,8 @@ export class HubConnection {
74
75
*
75
76
* The default value is 15,000 milliseconds (15 seconds).
76
77
* Allows the server to detect hard disconnects (like when a client unplugs their computer).
78
+ * The ping will happen at most as often as the server pings.
79
+ * If the server pings every 5 seconds, a value lower than 5 will ping every 5 seconds.
77
80
*/
78
81
public keepAliveIntervalInMilliseconds : number ;
79
82
@@ -604,24 +607,39 @@ export class HubConnection {
604
607
return ;
605
608
}
606
609
610
+ // Set the time we want the next keep alive to be sent
611
+ // Timer will be setup on next message receive
612
+ this . _nextKeepAlive = new Date ( ) . getTime ( ) + this . keepAliveIntervalInMilliseconds ;
613
+
607
614
this . _cleanupPingTimer ( ) ;
608
- this . _pingServerHandle = setTimeout ( async ( ) => {
609
- if ( this . _connectionState === HubConnectionState . Connected ) {
610
- try {
611
- await this . _sendMessage ( this . _cachedPingMessage ) ;
612
- } catch {
613
- // We don't care about the error. It should be seen elsewhere in the client.
614
- // The connection is probably in a bad or closed state now, cleanup the timer so it stops triggering
615
- this . _cleanupPingTimer ( ) ;
616
- }
617
- }
618
- } , this . keepAliveIntervalInMilliseconds ) ;
619
615
}
620
616
621
617
private _resetTimeoutPeriod ( ) {
622
618
if ( ! this . connection . features || ! this . connection . features . inherentKeepAlive ) {
623
619
// Set the timeout timer
624
620
this . _timeoutHandle = setTimeout ( ( ) => this . serverTimeout ( ) , this . serverTimeoutInMilliseconds ) ;
621
+
622
+ // Set keepAlive timer if there isn't one
623
+ if ( this . _pingServerHandle === undefined )
624
+ {
625
+ let nextPing = this . _nextKeepAlive - new Date ( ) . getTime ( ) ;
626
+ if ( nextPing < 0 ) {
627
+ nextPing = 0 ;
628
+ }
629
+
630
+ // The timer needs to be set from a networking callback to avoid Chrome timer throttling from causing timers to run once a minute
631
+ this . _pingServerHandle = setTimeout ( async ( ) => {
632
+ if ( this . _connectionState === HubConnectionState . Connected ) {
633
+ try {
634
+ await this . _sendMessage ( this . _cachedPingMessage ) ;
635
+ } catch {
636
+ // We don't care about the error. It should be seen elsewhere in the client.
637
+ // The connection is probably in a bad or closed state now, cleanup the timer so it stops triggering
638
+ this . _cleanupPingTimer ( ) ;
639
+ }
640
+ }
641
+ } , nextPing ) ;
642
+ }
625
643
}
626
644
}
627
645
@@ -813,6 +831,7 @@ export class HubConnection {
813
831
private _cleanupPingTimer ( ) : void {
814
832
if ( this . _pingServerHandle ) {
815
833
clearTimeout ( this . _pingServerHandle ) ;
834
+ this . _pingServerHandle = undefined ;
816
835
}
817
836
}
818
837
0 commit comments