How do I make an Observable Interval start immediately without a delay?

41,132

Solution 1

Before RxJs 6:

Observable.timer(0, 1000) will start immediately.

RxJs 6+

import {timer} from 'rxjs/observable/timer';
timer(0, 1000).subscribe(() => { ... });

Solution 2

RxJs 6. Note: With this solution, 0 value will be emitted twice (one time immediately by startWith, and one time by interval stream after the first "tick", so if you care about the value emitted, you could consider startWith(-1) instead of startWith(0)

interval(100).pipe(startWith(0)).subscribe(() => { //your code }); 

or with timer:

import {timer} from 'rxjs/observable/timer';
timer(0, 100).subscribe(() => {

    });

Solution 3

With RxJava2, there's no issue with duplicated first entry and this code is working fine:

io.reactivex.Observable.interval(1, TimeUnit.SECONDS)
        .startWith(0L)
        .subscribe(aLong -> {
            Log.d(TAG, "test");    // do whatever you want
    });

Note you need to pass Long in startWith, so 0L.

Solution 4

RxJava 2

If you want to generate a sequence [0, N] with each value delayed by D seconds, use the following overload:

Observable<Long> interval(long initialDelay, long period, TimeUnit unit)

initialDelay - the initial delay time to wait before emitting the first value of 0L

Observable.interval(0, D, TimeUnit.SECONDS).take(N+1)

You can also try to use startWith(0L) but it will generate sequence like: {0, 0, 1, 2...}

I believe something like that will do the job too:

Observable.range(0, N).delayEach(D, TimeUnit.SECONDS)
Share:
41,132

Related videos on Youtube

adamdport
Author by

adamdport

I'm obsessed with disc golf, have pet chickens, and 3D print whatever I can

Updated on May 28, 2021

Comments

  • adamdport
    adamdport almost 3 years

    I want my observable to fire immediately, and again every second. interval will not fire immediately. I found this question which suggested using startWith, which DOES fire immediately, but I then get a duplicate first entry.

      Rx.Observable.interval(1000).take(4).startWith(0).subscribe(onNext);
    

    https://plnkr.co/edit/Cl5DQ7znJRDe0VTv0Ux5?p=preview

    How can I make interval fire immediately, but not duplicate the first entry?

  • adamdport
    adamdport almost 7 years
    if I want the sequence to repeat, 0 prints immediately after 3 without a delay in-between. Is there a way to fix that? plnkr.co/edit/Muw5d4b8slOA3CcW4vXC?p=preview
  • Julia Passynkova
    Julia Passynkova almost 7 years
    try to do let obs$ = Rx.Observable.concat( Rx.Observable.timer(0, 1000).timestamp().take(4), Rx.Observable.timer(0, 1000).timestamp().take(4) ) .repeat(); but i am not sure.
  • adamdport
    adamdport almost 7 years
  • sercanD
    sercanD about 5 years
    for RxJs 6+ interval(100).pipe(startWith(0)).subscribe(() => { //your code });
  • Jette
    Jette over 4 years
    Regarding RxJs 6: You still need to import startWith (import { startWith } from 'rxjs/operators';)
  • Ste
    Ste over 2 years
    If I use startWith, my interval starts at the parameter value of startWith but on the 2nd iteration, goes back to zero IE - .startWith(6) gives a sequence of 6, 0, 1, 2, 3, 4
  • Rusty Rob
    Rusty Rob over 2 years
    yes, if you want 0,1,.. then timer is better. Startwith can be nice if you want to start with null or with -1 or something.