2

I read images from a live stream and select a batch periodically. I then send them to the server for validation. A HTTP error will be thrown if any fail validation. If that occurs I want to get a new batch of images.

this.input.getImages()
  .throttleTime(500)
  .switchMap(image =>

      new Observable<{}>(observer => {
        // Some operation
      })
      .map(i => ({ image, i }))

  ).filter(({ i }) =>  {
    // some filtering
  })
  .map(({ image }) => image)
  .take(6)
  .bufferCount(6)
  .map(images =>  // switch map??
    Observable.fromPromise(this.server.validate(images))
  )
  .retry(2)  // This only retrys the request, I want it to retry the whole chain (to get valid images)
  .subscribe(images => {
      console.log('All done')
    },
    err => {console.log(err)}
  )

The problem I'm having is that only the HTTP request gets retried since that is the new observable. There must be some way to encapsulate the beginning of the chain into a single Observable?

ovg
  • 1,486
  • 1
  • 18
  • 30

2 Answers2

1

See learnrxjs - retry. The example shows everything restarting from source onwards when an error is thrown.

The page shows pipe syntax, but the JSBin shows fluid operator syntax if you prefer.

The basic pattern is

const retryMe = this.input.getImages()
  .flatMap(val => {
    Observable.of(val)
      // more operators
  })
  .retry(2);
Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
  • Is it possible to get new values from `this.input.getImages()` when retrying? – ovg Mar 31 '18 at 23:07
  • Looking at the doc page, can see that source i.e interval(1000) restarts from 0 each time retry occurs, so yes I would expect this.input.getImages() to be fired again on retry. Easiest to try it and see! Of course, depends on the nature of getImages() - if it's a 'hot' observable (e.g a webcam), then you will get new images on retry. – Richard Matsen Mar 31 '18 at 23:13
  • ah ok got it now, I needed to take the throttleTime, take and bufferCount out of the inner Observable (duh). I was experiencing some odd behaviour. Thanks! – ovg Mar 31 '18 at 23:44
  • Actually, all that was wrong with my code was that I used `switchMap` instead of `flatMap`. No need for the `Observable.of(val)` in my case. – ovg Apr 01 '18 at 00:07
  • Well, the basic difference between `switchMap()` and `flatMap()` is that the former cancels the previous inner observable when a new input arrives. If there's no delay involved in `// Some operation` then they should both function in the same way. – Richard Matsen Apr 01 '18 at 00:15
1

Simple way is to wrap your complex observable in defer ans use retry on resulting observable.

Andrey Nikolaev
  • 368
  • 3
  • 9