0

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?

David Pfeffer
  • 38,869
  • 30
  • 127
  • 202
  • 2
    You 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 Answers1

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