66

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?

pjpscriv
  • 866
  • 11
  • 20
adamdport
  • 11,687
  • 14
  • 69
  • 91

4 Answers4

101

Before RxJs 6:

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

RxJs 6+

import {timer} from 'rxjs/observable/timer';
timer(0, 1000).subscribe(() => { ... });
pjpscriv
  • 866
  • 11
  • 20
Julia Passynkova
  • 17,256
  • 6
  • 33
  • 32
  • if I want the sequence to repeat, `0` prints immediately after `3` without a delay in-between. Is there a way to fix that? https://plnkr.co/edit/Muw5d4b8slOA3CcW4vXC?p=preview – adamdport May 24 '17 at 18:33
  • 1
    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. – Julia Passynkova May 24 '17 at 18:47
  • That helped! https://plnkr.co/edit/8KAcv2hgMLYMREzs4xvN?p=preview Thanks! – adamdport May 24 '17 at 19:33
48

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(() => {

    });
pjpscriv
  • 866
  • 11
  • 20
Rusty Rob
  • 16,489
  • 8
  • 100
  • 116
  • 2
    for RxJs 6+ interval(100).pipe(startWith(0)).subscribe(() => { //your code }); – sercanD Feb 01 '19 at 11:21
  • 1
    Regarding RxJs 6: You still need to import startWith (`import { startWith } from 'rxjs/operators';`) – Jette Sep 24 '19 at 05:56
  • 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 – Ste Sep 11 '21 at 20:06
  • 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. – Rusty Rob Sep 12 '21 at 06:27
9

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.

pjpscriv
  • 866
  • 11
  • 20
Micer
  • 8,731
  • 3
  • 79
  • 73
3

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)
Dymitr
  • 31
  • 1