Hello all.
First, apologies if there is already a topic for this. I searched and did not find anything similar or with a viable answer.
The setup: in our web app, it’s pretty common for us to query data based on user interaction, like doing a search. For this, it seemed to make the most sense to employ useLazyQuery. Our general use case is pretty straight forward:
- Page/containing component is already fully loaded
- User interacts, say by clicking a button
- Button handler calls a function that calls the query set up in useLazyQuery
- Response is handled in .then(…)
No real issues with that flow, except error handling, which is the reason for this post.
Our AGQL server is, for the most part, just a passthrough that aggregates different backend services. The queries just pass along the params to some REST endpoint, package the response, and send it back as the result of the query. (not worried about mutations in this case)
For the sake of discussion, I have classified three different scenarios where we do not get back expected data in our response:
- An error occurred in the backend service and that error is packaged as part of a normal response to the query, per our api spec.
- An error occurred somewhere in the AGQL server while making a call to the backend service(e.g. bad url, response structure changed, etc…). In this case we throw a new GraphQLError and let the AGQL framework handle the response to the query. It is thrown from the catch(…) block of a try/catch wrapping the code that calls the backend service and handles the http response.
- An error occurred somewhere in our client code, unrelated to the query itself.
For #1, we check the response for an error property, as specified in our own api spec.
For #3, we rely on the .catch(…) block of the promise and that works pretty well.
However, #2 is tripping us up. With useLazyQuery specifically, the .then(…) block is executed instead of the .catch(…) block, as was my first assumption, but it looks like that’s not the case. Please correct me if I am wrong.
So we next looked at the error and errors object in the response to the query, as we were seeing the error response in the network data (and that data’s structure was specific to an error being returned, unrelated to our spec). However, both error and errors properties of the response were undefined. We couldn’t locate the error info in the response at all.
We found that we had to include errorPolicy: ‘all’ (or similar) when calling the query to get data back in either error or errors.
The error property would contain error information if, for example, the query we tried to execute was malformed.
If, however, the error info was from, say, GraphQLError being thrown by the server, it would show up in errors. Problem there is the errors property is deprecated.
So this all raises a few questions:
- If errors is deprecated, how are errors thrown by the server expected to be handled?
- Why does useLazyQuery not behave it the expected way, where errors would be handled in the .catch(…) block first?
- Is there a better way to implement useLazyQuery? Or should we not be using it at all?
- Is our approach for error handling in the client incorrect in the context of Apollo?
- Is our AGQL server implementation bad (e.g. should we never throw an error, or GraphQLError error)?
Thank you in advance for any help. I will respond to follow-ups as quickly as possible.