question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Global `onSuccess` interceptor fires AFTER action `getData`?

See original GitHub issue

I 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:open
  • Created 3 years ago
  • Comments:7 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
klis87commented, Nov 6, 2020

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.

1reaction
avasurocommented, Feb 13, 2021

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:

import { createDriver as createAxiosDriver } from '@redux-requests/axios';
import axios from 'axios';

const axiosDriver = createAxiosDriver(axios);

const { requestsReducer, requestsMiddleware } = handleRequests({
   driver: {
       rest: axiosDriver,
       // Possible implementation with 'onResponse' interceptor on diver-level:
       slack: createAxiosDriver(axios, {
           onResponse(response) {
               if (response.status === 'ok') return response.object;
               else throw new SlackAPIError(response);
           }
       }),
       // Possible implementation with current architecture (on top of axios driver):
       slack: (requestConfig, requestAction, driverActions) => {
           return axiosDriver(requestConfig, requestAction, driverActions).then(response => {
               if (response.status === 'ok') return response.object;
               else throw new SlackAPIError(response);
           });
       }
   }
})
Read more comments on GitHub >

github_iconTop Results From Across the Web

Setting up Axios Interceptors for all HTTP calls in an application
Setting up Axios Interceptors for all HTTP calls in an application. Automatically intercept all the requests and responses so you don't have to ......
Read more >
How do I capture response of form.submit - Stack Overflow
This looks like exactly what I need, since I already have a PHP file that is handling many direct XMLHttpRequest()s on my page....
Read more >
Using Oracle Digital Assistant
Intent , determines whether the digital assistant can intercept and reroute ... For global actions, this variable controls the Show More global action...
Read more >
redux-saga-requests - npm
onRequest , onSuccess , onError and onAbort interceptors, ... So, again, after you dispatch a request action, after request is finished, ...
Read more >
redux-saga-requests - Bountysource
Global `onSuccess` interceptor fires AFTER action `getData`? $ 0. Created 2 years ago in klis87/redux-requests with 6 comments. I noticed that if you...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found