Global `onSuccess` interceptor fires AFTER action `getData`?
See original GitHub issueI noticed that if you put onSuccess
interceptor in handleRequests
, it is always fired after the getData
method of each individual action.
But consider this use case:
Many API’s include a “success” key in their responses, rather than using HTTP error codes (Slack for example uses an ok
key), so you might want to have a central place to process the API response and look for ok
or success
key, and remove them from the equation… For example.
Consider this response:
{
"ok": true,
"objects": []
}
So in your FETCH action you might use getData
:
getData: response => response['objects']
But this also means that your onSuccess
call no longer sees the ok
key at all, you just see the result of the getData
call…
handleRequests({
onSuccess: (response, action, store) => {
//response.data['ok'] is no longer there, it's been processed by `getData`.
return response;
},
...
})
I’m not sure if this is desired behavior or a bug, but I somehow feel that central interceptors should get the fresh data first and the actions get the data last… What do you think?
I am aware that we might just do processing of the response in the onSuccess
interceptor, but that will create inconsistent results of the actions getData
call sometimes touches the response data. The best case scenario is that the global interceptor homogenizes the response so that all actions always know what to expect if they need to getData
…
I suppose the easiest solution to this might be to have an onResponse
global interceptor? Since we also have no way of labeling a request as an error from onSuccess
…
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (5 by maintainers)
Top GitHub Comments
Re getData thx for your thoughts, indeed I also have mixed feelings about it
Re interceptors and cached queries, the issue is that they should be called for side effects, but not for data transformation 😃 And they cannot get raw data, because I store only transformed data. I do it on purpose, because otherwise people doing mutations would need to mutate both raw and transformed data, which would be terrible. Transformed data has to be stored and can be the only one source of truth, otherwise I won’t be able to have normalisation, caching, ssr, mutations working together, at least I dont know how otherwise. And caching reuses just data stored, cached queries doesnt have separate information, only that a query is cached and a timeout, which then makes dispatch(cachedRequest) not firing new request but getting data back from store.
I have some stuff to do before, but once I have a design plan for new interceptors, I will ping you so you might add some thoughts and worries before releasing the new version.
I didn’t managed to dive deep into all pros and cons mentioned here (lack of free time), but at a first glance I think it’s better to not implement global onSuccess interceptors or whatever handler to separate error and success responses because from my point of view responsibility to properly parse response and throw or not to throw error lies with Driver.
The reason is that, for example, slack API is not truly REST-based because it doesn’t follow all of REST rules (at least server can send error responses with status 200, which goes against the documentation), and this means that REST driver (fetch or axios) can’t properly handle such responses, and from my point of view to handle that API separate driver should be implemented. This driver should be build on top of some REST driver, and do additional handling of responses with status 200 (
if (status === "ok") then return response.object; else throw SomeEror();
)In addition beside standard REST API and those API’s that you’ve mentioned (like slack API etc.) there is many other protocols that never uses any of standard HTTP error responses, and includes information about possible error in response body. Examples of this protocols: JSON-RPC, XML-RPC, SOAP, GraphQL (which is implemented in this library via separate driver, by the way).
So, despite global onSuccess interceptor will be handy for end users of this library (especially for those who doesn’t know nothing about API of drivers) I think such interceptor will be a bad design decision. As a possible alternative - may be it will be good to add onResponse interceptor for axios and fetch drivers. This way it will be easier for end users to improve default HTTP behavior based on the needs, e.g. something like this: