The steps:
I have a source stream (observable) that is a web socket connection.
When the connection is disconnected or errors the source emits a error on the stream.
Downstream from the source I use retryWhen
to attempt a reconnect to the web socket connection after every x seconds.
Further downstream I have a catchError
that sets a default value. This allows the application to know the up-to-date status of the connection.
Example code (a very simplistic example of my code):
connect(): Observable<any> {
return this.websocket() // source stream that errors when it disconnects
.pipe(
retryWhen( errors =>
errors.pipe(
delay( 2000 ) // delay retry
)
)
)
}
connectionStatus(): Observable<boolean>{
return this.connect().pipe(
catchError( () => of( false ) ), // this does not trigger with the retryWhen
map( () => true )
)
}
The problem:
I want the downstream subscribers to know that it's disconnected while it is attempting the retryWhen
. However, the downstream catchError
is not triggered while retryWhen
is happening.
Any ideas how I can attempt re-connecting for all subscribers (not just the connectionStatus), but also when notify downstream when the connection is down (errors).
After re-connecting I want to continue streaming to all subscribers like nothing has happened.
Let me know if anything is unclear.
So writing this post helped me answer my own question.
/*
Basic stream handling no errors or retries..
*/
connect(){
return this.websocket();
}
/*
Have a stream that is always connected for all subscribers
*/
alwaysConnected(){
return this.connect().pipe(
retryWhen( errors => {
return errors.pipe(
delay( 2000 )
)
})
)
}
/*
use the continuous stream (no errors) and then in sub stream listen for the errors.
*/
connectionFails() {
return this.alwaysConnected().pipe(
switchMap( () => {
return this.connect().pipe( // switch to stream that errors
catchError( error => of( false ) ),
filter(connection => connection === false )
)
})
)
}
/*
Get a boolean for either a fail or success
*/
connectionStatus() {
return merge(
this.connectionFails(),
this.alwaysConnected().pipe( map( () => true ))
)
}
There were a couple of issues.
handling retry and catcherror
not completing a subscription when handling the error
There might be a simpler more elegant solution. Feel free to suggest.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.