I am trying to take a rxjs source observable, representing a network connection that pushes me data, and reconnect (by resubscribing to the source observable) if I have not received data within a timeout period. I can certainly write this in a somewhat hacky way, but is there a good way to write this concisely with rxjs?
Asked
Active
Viewed 201 times
0
-
2You can use `timeout()` and `retry()` operators but it's hard to tell what exactly you want to do from your description. without any code – martin Jun 30 '18 at 17:25
-
Why do you need to re-subscribe? If the source emits future data, your current subscription will receive it. – Meir Jun 30 '18 at 21:17
-
@Meir The source is a network connection. If the network connection has silently failed, the source will not emit any future data. – David Pfeffer Jul 01 '18 at 15:32
-
@martin I'm not sure how code would help here. Given a source observable, I want to resubscribe if nothing is emitted within a period of time, much like how `retry` / `retryWhen` resubscribe when an error is emitted. – David Pfeffer Jul 01 '18 at 15:33
1 Answers
0
I ultimately wrote an operator. I think there is a better way to do this, but seeing as how no one else has an idea either, here's the pipeable operator that I wrote:
import { Observable, Subscription } from "rxjs";
export function retryAfterTimeout<T>(timeout: number, allowCompletion = false): (obs: Observable<T>) => Observable<T> {
return source => new Observable<T>(observer => {
let sub: Subscription | undefined;
let timer: number | undefined;
function resetTimer() {
if (timer) clearTimeout(timer);
timer = window.setTimeout(() => resub(), timeout);
}
function resub() {
if (sub) sub.unsubscribe();
sub = source.subscribe({
next(x) {
resetTimer();
observer.next(x);
},
error(err) {
observer.error(err);
},
complete() {
if (allowCompletion)
observer.complete();
else
resub();
}
});
}
resub();
resetTimer();
return () => {
if (sub) sub.unsubscribe();
if (timer) window.clearTimeout(timer);
};
});
}

David Pfeffer
- 38,869
- 30
- 127
- 202