0

I have a list of Products an array products:Product[]

Using Observable and Observer next method, I want to emit each product to my UI after every 1 second. How can I accomplish this?

This is what I tried , it is producing an infinite loop.Any help will be much appreciated.

 public streamAllProducts(): Observable<Product> {
    const products = this.ds.getProducts();

    const sequence = new Observable((observer) => {

      products.forEach(element => {


        setTimeout(() => {
          observer.next(element);
        }, 1000
        );
      });


    });
    return sequence;
  }
SijoX
  • 77
  • 10

3 Answers3

0

You can use the delay operator and observer.complete()

UPDATED

  • The operator interval generates an observable with incrementing values each time you can use to iterate (infinite).
  • You can use a Subject to easy the generation.
  • You can handle the inner subscription and stop it when there are no more products to emit.
  public streamAllProducts(): Observable<Product> {
    const products = this.ds.getProducts();
    const sequence = new Subject<Product>();

    let timer: Subscription;
    timer = interval(1000).subscribe(index =>
      index < products.length
        ? sequence.next(products[index])
        : timer.unsubscribe()
    );    

    return sequence;
  }
nilsandrey
  • 1,030
  • 11
  • 28
0

Here is a working example.

The component that renders the desired effect will be doing the looping

https://stackblitz.com/edit/angular-pzrfj1

Supun De Silva
  • 1,437
  • 9
  • 15
  • Thanks Supun for this, I still wonder is it possible to handle in the service level where observable can emit the values sequentially at a specified time interval . – SijoX Apr 03 '20 at 07:18
  • Do not do that at the service. Let the service be a service. That is bad design practice in my opinion. open for debate. You can do it if really really necessary. – Supun De Silva Apr 03 '20 at 07:19
  • Added both since you insisted. I recommend the Presentation later to do the PRESENTATION and service layer do what it is suppose to do. But Both examples are now available – Supun De Silva Apr 03 '20 at 07:42
  • Thanks a lot, That was pretty fast. I am a beginner in Angular and RxJs, just wanted to explore the observable and to create a streaming effect with it. Thank you very much for your design tips. – SijoX Apr 03 '20 at 08:40
0

Just use the rx operator distinctUntilChanged to compare a new array length and do something:

myObservableArray
  .pipe(
    distinctUntilChanged(
      (value1: valueModel, value2: valueModelModel) =>
        value1?.prop.length === room2?.prop.length
    ),
    tap(() => //do something)
  )
sɐunıɔןɐqɐp
  • 3,332
  • 15
  • 36
  • 40