Angular 4.3 Observables: How to retry at intervals and maximum retries?

I am new to Angular 4.3. I have a mapping application that displays a “map layer” by loading a series of small images (“tiles”). At startup, the map layer may take from 0.1 to 5.0 seconds to load.

I need to trigger an event when the client received two or more fragments. I thought I could achieve this by signing up for an Observable, which retries up to 30 times, in an interval of 200 ms.

Still:

  public updateTileContainer() {
    this._getTileContainer().subscribe(container => {
      if (container) {
        console.log('* do stuff with container *');
      }
    });
  }

  private _getTileContainer(): Observable<any> {

    return Observable.interval(200)
      .mergeMap(function (n) {

        const tileImages = $('#mymap').find('img[src*=\'kml\']');

        console.log(`Retry ${n}: ${tileImages.length} tiles found`);

        if (!tileImages || tileImages.length < 2) {
          return Observable.of(null);
        }

        const tileContainer = getContainer(tileImages);

        return Observable.of(tileContainer);
      })
      .take(30);
  }

It works! Like. I get this output:

Retry 0: 0 tiles found
Retry 1: 0 tiles found
Retry 2: 0 tiles found
Retry 3: 0 tiles found
Retry 4: 0 tiles found
Retry 5: 0 tiles found
Retry 6: 0 tiles found
Retry 7: 2 tiles found
* do stuff with container *
Retry 8: 3 tiles found
* do stuff with container *
Retry 9: 9 tiles found
* do stuff with container *
Retry 10: 12 tiles found
* do stuff with container *
etc.

What I'm actually trying to do is to emit one event in "Retry 7" and then stop dispensing.

, "" , ? "" 0 6, ? Observable, 30 , ?

+4
3

.retry(count)

, 2 . retry() 30 .

NB: 30- , , . (. ).

public updateTileContainer() {
  this._getTileContainer().subscribe(container => {
      console.log('* do stuff with container *');
  },error=>{
      console.log('no container found !');
  });
}

private _getTileContainer(): Observable <any> {
  return Observable.timer(200).map(()=>{
    const tileImages = $('#googlemap').find('img[src*=\'kml\']');
    if (tileImages.length <= 2)
      throw new Error("not enough tiles !");
    return getContainer(tileImages);
  })
  .retry(30);
}

@JonStødle . , , - . , , Observable , .

, , .

+3

, - .

. :

private _getTileContainer(): Observable<any> {

return Observable.interval(200)
    .map(_ => $('#googlemap').find('img[src*=\'kml\']')) // 1
    .take(30) // 2
    .skipWhile(tiles = tiles.length < 2) // 3
    .map(tiles => getContainer(tiles)) // 4
    .take(1); // 5
}
  • .
  • , 30 .
  • , , 2 .
  • .
  • 1 .
+2

, , ,

public updateTileContainer() {
  this._getTileContainer().subscribe(container => {

      console.log('* do stuff with container *');

  });
}


private _getTileContainer(): Observable<any> {

  return Observable.interval(200)
    .concatMap(n => {
      let tileContainer: any = null;

      const tileImages = $('#googlemap').find('img[src*=\'kml\']');         
      if (tileImages.length >= 2) {
        tileContainer = getContainer(tileImages);
      }

      return Observable.of(tileContainer);
    })
    .take(30)
    .filter(res => res !== null)
    .take(1);
}

Thus, based on the original example, the main Observable emits nullsfor the first 6 or 7 retries, but filter()stops them from being transmitted to the subscriber. take(30)stops the main observation after 30 repetitions, whereas take(1)after it filter()stops the Observable after the first non-zero repeat.

0
source

Source: https://habr.com/ru/post/1687514/


All Articles