Error handling on client in GraphQL - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When a client handles errors from a GraphQL query, it often checks the response for error messages. We want to understand how the time to handle these errors changes as the number of errors or data size grows.
How does the client's work increase when there are more errors or more data to check?
Analyze the time complexity of the following code snippet.
query GetUsers {
users {
id
name
}
}
// Client-side pseudo-code:
const response = await fetchGraphQL(query);
if (response.errors) {
response.errors.forEach(error => handleError(error));
} else {
displayData(response.data.users);
}
This code fetches a list of users and checks if there are any errors. If errors exist, it processes each error one by one.
- Primary operation: Looping through the list of errors with
forEachto handle each error. - How many times: Once for each error in the
response.errorsarray.
As the number of errors increases, the client must handle each one separately.
| Input Size (number of errors) | Approx. Operations |
|---|---|
| 10 | 10 error handling calls |
| 100 | 100 error handling calls |
| 1000 | 1000 error handling calls |
Pattern observation: The work grows directly with the number of errors. More errors mean more handling steps.
Time Complexity: O(n)
This means the time to handle errors grows in a straight line with the number of errors received.
[X] Wrong: "Handling errors is always fast and constant time, no matter how many errors there are."
[OK] Correct: Each error requires separate processing, so more errors mean more work and longer handling time.
Understanding how error handling scales helps you write efficient client code and shows you can think about performance in real situations.
"What if the client also had to retry fetching data for each error? How would that affect the time complexity?"
Practice
Solution
Step 1: Understand client-side error handling
Error handling on the client is about managing problems that happen when fetching or processing data, so the app doesn't crash.Step 2: Identify the main goal
The goal is to keep the app stable and inform users clearly about what went wrong.Final Answer:
To keep the app stable and show clear messages to users -> Option BQuick Check:
Error handling = stability + clear messages [OK]
- Thinking error handling speeds up server
- Confusing error handling with schema changes
- Assuming error handling stores data
Solution
Step 1: Recall promise error handling syntax
Promises use.then()for success and.catch()for errors.Step 2: Match correct chaining
The correct order is.then(...).catch(...). client.query(...).then(...).catch(error => handleError(error)) matches this.Final Answer:
client.query(...).then(...).catch(error => handleError(error)) -> Option AQuick Check:
Promise catch method = .catch() [OK]
- Placing .catch() before .then()
- Using non-existent .try() or .error() methods
- Ignoring promise chaining order
client.query({ query: GET_USER })
.then(response => console.log('User:', response.data.user))
.catch(error => console.log('Error:', error.message))Solution
Step 1: Understand promise flow on failure
If the query fails, the.catch()block runs, logging the error message.Step 2: Identify logged output
The console logs 'Error:' followed by the error message from the server.Final Answer:
Error: [error message from server] -> Option DQuick Check:
Failed query triggers .catch() logging error [OK]
- Assuming .then() runs on failure
- Expecting 'User: undefined' instead of error
- Thinking no output appears on error
try {
const response = await client.query({ query: GET_POSTS });
console.log(response.data.posts);
} catch {
console.log('Failed to fetch posts');
}Solution
Step 1: Review try-catch syntax
The catch block should include an error parameter to access error details.Step 2: Identify missing error parameter
The code usescatch { ... }without(error), preventing access to the error details.Final Answer:
Missing error parameter in catch block -> Option CQuick Check:
catch needs (error) parameter [OK]
- Omitting error parameter in catch
- Thinking await is invalid in try
- Believing client.query is not a promise
async function submitData() {
try {
const result = await client.mutate({ mutation: ADD_ITEM, variables: { name: 'Book' } });
console.log('Item added:', result.data.addItem.id);
} catch (error) {
if (error.networkError) {
alert('Network problem, please try again later.');
} else {
alert('An error occurred.');
}
}
}Solution
Step 1: Analyze error handling logic
The catch block checks if the error is a network error and shows a specific message.Step 2: Confirm correct usage of await and alerts
Using await with client.mutate is valid, and alerts are acceptable for user messages.Final Answer:
This code correctly distinguishes network errors and shows messages -> Option AQuick Check:
Check error.networkError to show friendly messages [OK]
- Ignoring networkError property in catch
- Thinking alerts are disallowed
- Misunderstanding await usage with mutate
