Hi guys, I got an incident that might be an issue.
This code below runs every time the page is loaded.
const getClasses = () => Observable.fromPromise(
api.get('URL')
)
const startApp = data => {
var host = 'API'
return Observable.fromPromise(
api.get(host)
)
}
export const LoadContentEpic = (action$, state) =>
action$.ofType(LOAD_APP)
.mergeMap(action =>
getClasses()
.mergeMap(response =>
startApp(response.data)
.mergeMap(res =>
Observable.of(loadAppFulfilled(res))
)
)
)
.catch(error =>
Observable.merge(
Observable.of(loadAppRejected(error)),
Observable.of(push('/'))
)
)
.retry()
If token has expired or trigger some error, it redirects to login page.
The problem occurs when user do login again and 'LoadContentEpic' does not trigger.
Is that the right use for 'retry()'?
Thx guys!
My fault. Working now.
@fedbalves What did you change? It happens for me as well.
If you place a retry after a catch, it will only retry if there was an exception inside the catch callback itself. All other errors will be caught by the catch operator.
If you want the same behavior of retry but need to use catch to emit something first before restarting, you can use the second argument provided to your catch callback, which is the source Observable that you applied the operator to; i.e. the operator chain above it. This works because Observables are lazy, so subscribing to the source starts it up again.
.catch((error, source) =>
Observable.merge(
Observable.of(loadAppRejected(error)),
Observable.of(push('/')),
source // <------------------- merge in the previous source
)
)
Observable.of also supports an arbitrary number of arguments, so you can just do
.catch((error, source) =>
Observable.merge(
Observable.of(loadAppRejected(error), push('/'))
source
)
)
All that said, you should most likely catch the error before it reaches the top-level observer chain. So catch the error inside your mergeMap. Then you won't need to restart anything. This is often called "isolating your observer chains"
const LoadContentEpic = (action$, state) =>
action$.ofType(LOAD_APP)
.mergeMap(action =>
getClasses()
.mergeMap(response =>
startApp(response.data)
.mergeMap(res =>
Observable.of(loadAppFulfilled(res))
)
)
.catch(error => Observable.of(
loadAppRejected(error),
push('/')
))
);
Thanks for this great explanation. Everything works fine now :+1:
Most helpful comment
If you place a retry after a catch, it will only retry if there was an exception inside the catch callback itself. All other errors will be caught by the catch operator.
If you want the same behavior of retry but need to use catch to emit something first before restarting, you can use the second argument provided to your catch callback, which is the source Observable that you applied the operator to; i.e. the operator chain above it. This works because Observables are lazy, so subscribing to the source starts it up again.
Observable.ofalso supports an arbitrary number of arguments, so you can just doAll that said, you should most likely catch the error before it reaches the top-level observer chain. So catch the error inside your
mergeMap. Then you won't need to restart anything. This is often called "isolating your observer chains"