fetch: How to get the response json on HTTP error 400+ ?
Suppose I create a request to http://example.com/404, and the response is 404 status code with a json response like this:
{
"type": "error",
"message": "What you were looking for isn't here."
}
How can I get the above json using fetch?
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 15 (2 by maintainers)
Here is the code similar to @lasergoat, but handles json regardless of the
response.status. Also in case of network error, rejects with a custom error objectHey, just want to let you know, I settled on a fair way of doing what I needed. I thought I’d post just in case anyone else ends up in a situation similar to me where they couldn’t use a catch because fetch gives a ReadableByteStream instead of a json object.
This solution keeps your code clean and semantic. You use it like this:
or
How would you catch both a 200 OR a 422 from a resource, both containing valid JSON in the body?
This is the only way I’ve figured it out so far.
To produce generic error objects I create a wrapper around the response and reject the promise. Finally throw the wrapped object. This produces a clean response on which higher level functions can depend.
use it like:
Instead of depending on the body (JSON) to contain an indicator I think it’s nicer to only look at the status. Downside is having to pass multiple arguments.
I ended up doing something like this. Probably not best but definitelly one of the shortes solutions. I just did not want to look at all those nested promises.
@Siilwyn Agree, I always use response.ok and response.status to determine next action. Unfortunately, consider the fact that you might also want to return an error status with an error message as a JSON response…
Nice @Siilwyn but I had some responses as blobs and others as jsons so I have to check headers first, because in your promise, it always returns a json.
And use it on the fetch
Just came to thank you guys!
I’m not that familiar with Javascript and spent way too much time with this but I ended up with a solution that was similar to, but not quite as beautiful as, the solution provided by @Siilwyn. I actually stumbled upon this page quite early in my research but didn’t know enough Javascript to recognize the solution staring in my face. So I’m going to take the time to explain it for future generations. 😉
The way I see it any call to fetch will result in one of the following four outcomes:
In order for our application to be robust it must be able to deal with all these outcomes. The original question stems from the problem that the response and json objects aren’t available in the same context. Use Promise.all() to fix that.
Network- and parsing errors causes exceptions and it would be nice to unify our error handling. Throw an Error when you get a business logic error message from the server. That way all types of errors end up in the catch-method.
Finally I’m guessing the original question stems from a desire to provide good error messages. Business logic error messages will be provided by the server but the network- and parsing error messages must be provided by us. In the example below I’ve created a map with the Exception type as the key and I’m using exception.constructor to do the lookup. Note that network- and parsing error messages are provided in place and that business logic error messages are grabbed from the exception which in turn was created using the message provided by the server.
Welp, here’s mine:
Just make sure to always return a JSON parsable body in your responses and you should be good!