R01010010
R01010010

Reputation: 5968

RxJS Observable.combineLatest never completes

One of my Observable.combineLatest never completes because one of its observables never gets to emit a value, so the completion function is never reached.

Is there a way so I can set a kind of a timeOut so after it I can provide a default value for it? or at least a way to tell which observable is not emiting any data at all?

Something like

Observable.combineLatest(...).onTimeOut(() => console.log('No data from 3th observable')

Edit:

So given this:

Observable.combineLatest(
  observable1, // <- ok
  observable2, // <- ok
  observable3, // <- timeout
  observable4, // <- ok
  observable5, // <- ok
  (...args) => ({...args})
)
.pipe(
  timeout(1*1000),
  catchError((e) => {
    console.log(e)
    return Observable.of({})
  })
)
.subscribe(() => {})

How can I tell that observable3 was the responsible of the timeout?

Upvotes: 1

Views: 1104

Answers (1)

Sam Herrmann
Sam Herrmann

Reputation: 6986

You can use the timeout and catchError operator (or just timeoutWith, see edit below) for this use case:

combineLatest(...).pipe(
  timeout(myTimeoutValueInMilliseconds),
  // Catch the error thrown by the timeout and return a default value instead.
  catchError(() => of('my default value'))
).subscribe(e => console.log(e))

Of course if you need the timeout on only one of the Observables then you can restructure it as follows:

combineLatest(
   myObsOne.pipe(
    timeout(myTimeoutValueInMilliseconds),
    catchError(() => of('my default value'))
  ),
  myObsTwo
).subscribe(e => console.log(e))

Edit

As pointed out by Oles Savluk in the comments, you can simplify this solution by using timoutWith instead of timeout and catchError:

combineLatest(
   myObsOne.pipe(
    timeoutWith(myTimeoutValueInMilliseconds, of('my default value')),
  ),
  myObsTwo
).subscribe(e => console.log(e))

Upvotes: 1

Related Questions