rxjs infinite loop with an interval variable

6.3k views Asked by At

I want to make infinite loop with an interval variable using rxjs Observable so I'm trying to rewrite this function in rxjs

takeAWalk(player){
    setTimeout(() => {

      console.log("Player is walking...");

      takeAWalk(player);
    }, getRandomDelayBetween(1000, 2500));
}

I tried

Observable
  .timer(0, getRandomDelayBetween(1000, 2500))
  .take(10)
  .timeInterval()
  .subscribe(res=>{
    console.log("player is walking ...");
  });

but the problem that this is finite to 10 and the interval is constant (getRandomDelayBetween is only called once).

Which operators should I use to produce the same functionality of takeAWalk function?

2

There are 2 answers

0
Olaf Horstmann On BEST ANSWER

There are many ways to write this in rxjs, you could try something like this:

Rx.Observable.of(null)
  .concatMap(() => Rx.Observable.timer(Math.random() * 1500))
  .do(() => console.log("player is walking ..."))
  .repeat()  // optionally .repeat(10)
  .subscribe();

Check out the example live here: http://jsbin.com/levakipunu/edit?js,console

0
Kevin Upton On

Just to expand on the expand :')

This is a runWhile function I created, which acts like a while loop, with a bonus interval value, to delay the event between each loop.

It will not continue through the loop until the condition is false.

import { EMPTY, Observable, of, OperatorFunction } from 'rxjs';
import { delay, expand, filter, flatMap, mapTo } from 'rxjs/operators';

/**
 * Like a while loop for RxJS,
 * while (condition()) { doFn() }
 *
 * @param condition
 * @param doFn
 * @param interval
 * @param initialValue
 */
export function runWhile<T = any> (
  condition : () => boolean,
  doFn : () => Observable<T>,
  interval = 0,
  initialValue = null,
) : OperatorFunction<T, T> {
  return flatMap<T, T>((initial) => {
    return of(condition())
      .pipe(
        expand((cond) => {
          if (cond === false) {
            return EMPTY;
          }

          return doFn().pipe(delay(interval), mapTo(condition()));
        }),
        filter(cond => cond === false),
        mapTo(initial),
      );
  });
}

See this codepen for an example of how it works. CodePen