@@ -98,6 +98,7 @@ export class TimeSync implements TimeSyncApi {
98
98
#latestDateSnapshot: Date ;
99
99
#subscriptions: SubscriptionEntry [ ] ;
100
100
#latestIntervalId: number | undefined ;
101
+ #currentRefreshInterval: number ;
101
102
102
103
constructor ( options : Partial < TimeSyncInitOptions > ) {
103
104
const {
@@ -116,45 +117,82 @@ export class TimeSync implements TimeSyncApi {
116
117
this . #latestDateSnapshot = initialDatetime ;
117
118
this . #subscriptions = [ ] ;
118
119
this . #latestIntervalId = undefined ;
120
+ this . #currentRefreshInterval = Number . POSITIVE_INFINITY ;
119
121
}
120
122
121
- #reconcileRefreshIntervals( ) : void {
122
- if ( this . #subscriptions. length === 0 ) {
123
- this . #clearInterval( this . #latestIntervalId) ;
124
- return ;
123
+ #onSubscriptionAdd( ) : void {
124
+ if ( this . #resyncOnNewSubscription) {
125
+ this . #updateSnapshot( ) ;
125
126
}
126
127
127
- const prevFastestInterval =
128
- this . #subscriptions[ 0 ] ?. targetRefreshInterval ?? Number . POSITIVE_INFINITY ;
129
- if ( this . #subscriptions. length > 1 ) {
130
- this . #subscriptions. sort (
131
- ( e1 , e2 ) => e1 . targetRefreshInterval - e2 . targetRefreshInterval ,
132
- ) ;
133
- }
128
+ // Sort by refresh speed, descending
129
+ this . #subscriptions. sort (
130
+ ( e1 , e2 ) => e1 . targetRefreshInterval - e2 . targetRefreshInterval ,
131
+ ) ;
134
132
133
+ const oldFastestInterval = this . #currentRefreshInterval;
135
134
const newFastestInterval =
136
135
this . #subscriptions[ 0 ] ?. targetRefreshInterval ?? Number . POSITIVE_INFINITY ;
137
- if ( prevFastestInterval === newFastestInterval ) {
136
+ if ( oldFastestInterval === newFastestInterval ) {
138
137
return ;
139
138
}
140
- if ( newFastestInterval === Number . POSITIVE_INFINITY ) {
141
- this . #clearInterval( this . #latestIntervalId) ;
139
+
140
+ this . #currentRefreshInterval = newFastestInterval ;
141
+ this . #clearInterval( this . #latestIntervalId) ;
142
+ this . #latestIntervalId = undefined ;
143
+ if ( this . #currentRefreshInterval === Number . POSITIVE_INFINITY ) {
142
144
return ;
143
145
}
144
146
145
- /**
146
- * @todo Figure out the conditions when the interval should be set up,
147
- * and when/how it should be updated
148
- */
149
- this . #latestIntervalId = this . #setInterval( ( ) => {
150
- this . #latestDateSnapshot = this . #createNewDatetime(
151
- this . #latestDateSnapshot,
147
+ const newTime = this . #createNewDatetime( this . #latestDateSnapshot) ;
148
+ const elapsed =
149
+ newTime . getMilliseconds ( ) - this . #latestDateSnapshot. getMilliseconds ( ) ;
150
+
151
+ const startNewIntervalFromScratch = ( ) => {
152
+ this . #latestIntervalId = this . #setInterval(
153
+ ( ) => this . #updateSnapshot( ) ,
154
+ this . #currentRefreshInterval,
152
155
) ;
153
- this . #flushUpdateToSubscriptions( ) ;
154
- } , newFastestInterval ) ;
156
+ } ;
157
+
158
+ const unfulfilled = Math . max ( 0 , this . #currentRefreshInterval - elapsed ) ;
159
+ if ( unfulfilled === 0 ) {
160
+ startNewIntervalFromScratch ( ) ;
161
+ return ;
162
+ }
163
+
164
+ // Feels a bit hokey to be setting a timeout via setInterval, but
165
+ // didn't want to add even more data dependencies to the constructor
166
+ // when setInterval can be used just fine in a pinch
167
+ this . #latestIntervalId = this . #setInterval( ( ) => {
168
+ this . #clearInterval( this . #latestIntervalId) ;
169
+ this . #latestIntervalId = undefined ;
170
+ startNewIntervalFromScratch ( ) ;
171
+ } , unfulfilled ) ;
172
+ }
173
+
174
+ /**
175
+ * @todo This isn't done yet
176
+ */
177
+ #onSubscriptionRemoval( ) : void {
178
+ if ( this . #subscriptions. length === 0 ) {
179
+ this . #clearInterval( this . #latestIntervalId) ;
180
+ this . #latestIntervalId = undefined ;
181
+ this . #currentRefreshInterval = Number . POSITIVE_INFINITY ;
182
+ return ;
183
+ }
184
+
185
+ const newFastestInterval =
186
+ this . #subscriptions[ 0 ] ?. targetRefreshInterval ?? Number . POSITIVE_INFINITY ;
187
+ if ( newFastestInterval === this . #currentRefreshInterval) {
188
+ return ;
189
+ }
155
190
}
156
191
157
- #flushUpdateToSubscriptions( ) : void {
192
+ #updateSnapshot( ) : void {
193
+ this . #latestDateSnapshot = this . #createNewDatetime(
194
+ this . #latestDateSnapshot,
195
+ ) ;
158
196
for ( const subEntry of this . #subscriptions) {
159
197
subEntry . onUpdate ( this . #latestDateSnapshot) ;
160
198
}
@@ -171,7 +209,7 @@ export class TimeSync implements TimeSyncApi {
171
209
}
172
210
173
211
this . #subscriptions = updated ;
174
- this . #reconcileRefreshIntervals ( ) ;
212
+ this . #onSubscriptionRemoval ( ) ;
175
213
}
176
214
177
215
subscribe ( entry : SubscriptionEntry ) : void {
@@ -184,7 +222,7 @@ export class TimeSync implements TimeSyncApi {
184
222
const subIndex = this . #subscriptions. findIndex ( ( s ) => s . id === entry . id ) ;
185
223
if ( subIndex === - 1 ) {
186
224
this . #subscriptions. push ( entry ) ;
187
- this . #reconcileRefreshIntervals ( ) ;
225
+ this . #onSubscriptionAdd ( ) ;
188
226
return ;
189
227
}
190
228
@@ -195,7 +233,7 @@ export class TimeSync implements TimeSyncApi {
195
233
196
234
this . #subscriptions[ subIndex ] = entry ;
197
235
if ( prev . targetRefreshInterval !== entry . targetRefreshInterval ) {
198
- this . #reconcileRefreshIntervals ( ) ;
236
+ this . #onSubscriptionAdd ( ) ;
199
237
}
200
238
}
201
239
}
0 commit comments