How do I create a timeout?
This inaugural post is in the format I hope to follow going forward: a question, a discussion of the question, a solution or several solutions (each linked to a demo), and a teaser for the next question. The point of the teaser is to stimulate some discussion of possible solutions from readers, but I will be sincerely shocked if the first few posts even get readers, let alone discussion from them. The assumption is that every reader knows the basics of RxJs. On the left is a link to the documentation for RxJs; that may clarify some things.
If the question is, “How do I create an Operator that allows its source Observable to run for given time and then ends it?”, that’s pretty simple:
function timeout(n) {
return takeUntil(timer(n));
}
Code is here.
But the question is, “How do I create an Operator that copies its source Observable, until the source fails to emit for given time?”, it’s somewhat more complicated.
The key insight is that switchMap() will unsubscribe from one inner Observable when the source emits the next value. So:
function timeoutE(n) {
const timeoutSentinel = Symbol();
return pipe(
switchMap(v => timer(n).pipe(
mapTo(timeoutSentinel),
startWith(v))),
takeWhile(v => v !== timeoutSentinel),
);
}
Code is here.
Next time: “How do I check if an Observable is still running?”
This seems like a special case of the "take until something external happens" problem. What's "iffy" about using a sentinal?
ReplyDeleteI'm just not happy with the type. If this were TypeScript, the type of the switchMap() would by T | Symbol. It might be possible to mark the takeWhile so the compiler realizes it's effectively a type-guard, but I dunno, it bugs me a little. Of course, I don't have a better idea...
Delete