Reputation: 343
To handle 401 unauthorized requests, I've tried to wrap all of my api requests with an errorHandler:
const apiGet (props) = ajax({
headers,
method: 'GET',
...props
}).catch(res => {
if (res.status === 401)
return Observable.of(unauthorizedAction();
else
return Observable.throw(res);
});
Ideally, I could use it in the following way, knowing that a 401 would trigger unauthorizedAction()
, while say a 500 would be handled by handleOtherErrors
.
action.ofType(SOME_ACTION) =>
apiGet(something)
.map(res => doSomethingWithResponse(res))
.catch(handleOtherErrors);
However, with the setup above, the problem arises when I get a 401 response. The errorHandler returns unauthorizedAction as expected, but then it continues to map the action and try to do something with the response, instead of dispatching that action and terminating the Observable chain.
So, my question is, how could I do something like this in my error handler?
.catch(res => {
if (res.status === 401)
// Dispatch an action, but stop the rest of the chain
else
return Observable.throw(res);
}).map(...restOfChain)
.catch(additionalErrorHandlerForNon401);
Upvotes: 1
Views: 71
Reputation: 15401
Operators are a chain of Observables that have no knowledge of how or what previous or later operators do. It's possible to create your own custom series of operators that would have such knowledge and power, but I don't recommend it as it goes against the traditional RxJS pattern.
Instead, you could pass along a result selector that will be applied using map
for them.
// provides a default `resultSelector` that is basically a noop
const apiGet = (props, resultSelector = res => res) =>
ajax({ headers, method: 'GET', ...props })
.map(res => resultSelector(res))
.catch(res => {
if (res.status === 401)
return Observable.of(unauthorizedAction());
else
return Observable.throw(res);
});
It could then be used like this:
apiGet(something, res => doSomethingWithResponse(res))
.catch(handleOtherErrors)
When the action creator has the same signature as the resultSelector
you could even just pass it as-is
apiGet(something, doSomethingWithResponse)
.catch(handleOtherErrors)
Upvotes: 3