0

I'm looking for a way to have my observable emit on intervals. I have a service that handles it, and components that use the subject to emit values and a component that need to recieve it on a 6 second interval.

export class Service {

  constructor() {}

  private subject = new Subject<string>();
  public observable$ = this.toastMessage.asObservable();

  updateSubject(data) {
     this.subject.next(data);
  }

}

// somewhere else
export class Component {

  constructor(private srv: Service) {}

  ngOnInit() {
    this.srv.observable$.subscribe(data => {
       console.log(data, 'should emit once every 6 seconds');
    })
  }
}

// also elsewhere
export class ComponentUpdater {

  constructor(private srv: Service) {}

  ngOnInit() {
    this.srv.updateSubject('way');
    this.srv.updateSubject('to');
    this.srv.updateSubject('fast');
  }
}

Does anyone know how I can do it with Subject?

Jonathan002
  • 9,639
  • 8
  • 37
  • 58
  • possible duplicate of [this](https://stackoverflow.com/questions/37994059/angular2-observable-with-interval) or [this](https://stackoverflow.com/questions/35316583/angular2-http-at-an-interval) – Fateme Fazli May 06 '18 at 07:17
  • there is a fundamental difference in "updating the values (of the `Subject`) every 6 seconds" and "listening to an observable every 6 seconds". Which one do you want to achieve? – CozyAzure May 06 '18 at 07:19
  • @CozyAzure I want the subscriber to receive all the values emitted during its subscription time every 6 seconds. – Jonathan002 May 06 '18 at 07:21
  • @fatemefazli I'm trying to get it to work with 'Subject' attached to it – Jonathan002 May 06 '18 at 07:28

2 Answers2

0

Make sure to import interval

import 'rxjs/add/observable/interval';

and then

   Observable.interval(6000).subscribe( x => {
          this.srv.observable$.subscribe(data => {
          console.log(data, 'should emit once every 6 seconds');
         })
   })
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • But how do I send the observable data to emit? I'm trying to use 'subject' so that the observable only emits and can't be modified directly. – Jonathan002 May 06 '18 at 07:22
  • This code also skips some values when other components update the 'Subject' and just keeps emitting the same last value every 6 seconds – Jonathan002 May 06 '18 at 07:48
0

You can achieve this by using the bufferTimer-operator

import { bufferTime, filter } from 'rxjs/operators';

export class Service {

  constructor() {}

  private subject = new Subject<string>();
  public observable$ = this.toastMessage.asObservable();

  updateSubject(data) {
    this.subject.next(data);
  }

}

// somewhere else
export class Component {

  constructor(private srv: Service) {}

  ngOnInit() {
    this.srv.observable$
      .pipe(
        bufferTime(6000),
        filter (data => data.length)
      )
      ^^^^^^^^^^^^^^^^^^^^^^^
      .subscribe(data => {
      console.log(data, 'should emit once every 6 seconds');
    })
  }
}

// also elsewhere
export class ComponentUpdater {

  constructor(private srv: Service) {}

  ngOnInit() {
    this.srv.updateSubject('way');
    this.srv.updateSubject('to');
    this.srv.updateSubject('fast');
  }
}
Leon
  • 480
  • 4
  • 8
  • Tried using the buffer operator but it throws the error "TypeError: Cannot read property 'lift' of undefined" -- The type error when hovering over it also shows: "The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<{}>'." -- I'm not sure, but I think it might have to do with how my observable was created via .asObservable() -- I'm not sure if I should add any more parameters or do something different with the observable created. – Jonathan002 May 08 '18 at 04:32
  • @Jonathan002 sorry, somehow i messed up the imports. Try importing it from `rxjs/operators` – Leon May 08 '18 at 05:43
  • Thanks for the update. I've tried this, but it emits all the items at once and just emits a blank array every 6 seconds.. I'm hoping to find something that can catch everything emited.. var catch = ['way', 'too', 'fast']. but slow down and run the subscribe function once every 6 seconds for each of the data it caught being.. 0sec - data = catch[0]... 6sec later - data = catch[1]... 12sec later data = catch[2] ... if catch = [] the subscribe function should not be called anymore.. – Jonathan002 May 08 '18 at 11:39
  • @Jonathan002 you could filter out empty arrays – Leon May 08 '18 at 19:23