Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use fetch(), read response body from non HTTP OK status codes and catch the exception

I have been reading up on fetch() and how to catch and print a readable error message from the server. Ideally I would like to throw an error that always ends up in Catch 2 in my example below and that console.log(`OK: ${data}`); is not ran if there is an error. I can mitigate console.log(`OK: ${data}`); by running then directly on response.json(); instead but I would like to know the proper way of achieving this.

https://stackoverflow.com/a/44576265/3850405

https://developers.google.com/web/updates/2015/03/introduction-to-fetch

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

C#:

[HttpGet, Route("api/specific/catalog/test")]
public async Task<IHttpActionResult> Test()
{
    return InternalServerError(new Exception("My Exception"));
}

[HttpGet, Route("api/specific/catalog/test2")]
public async Task<IHttpActionResult> Test2()
{
    return Ok("My OK Message");
}

Typescript:

fetch('api/specific/catalog/test2')
    .then(response => {
        if (!response.ok) {
            response.text().then(text => {
                throw new Error(`Request rejected with status ${response.status} and message ${text}`);
            })
            .catch(error =>
                console.log(`Catch 1: ${error}`)
            );
        }
        else {
            return response.json();
        }
    })
    .then(data => {
        console.log(`OK: ${data}`);
    })
    .catch(error =>
        console.log(`Catch 2: ${error}`)
    );

OK:

enter image description here

Exception:

enter image description here

I guess I could do something like this to catch all errors but it seems weird:

fetch('api/specific/catalog/test')
    .then(response => {
        if (!response.ok) {
            response.text().then(text => {
                throw new Error(`Request rejected with status ${response.status} and message ${text}`);
            })
            .catch(error =>
                console.log(`Catch: ${error}`)
            );
        }
        else {
            return response.json().then(data => {
                console.log(`OK: ${data}`);
            })
            .catch(error =>
                console.log(`Catch 2: ${error}`)
            );
        }
    })
    .catch(error =>
        console.log(`Catch 3: ${error}`)
    );
like image 225
Ogglas Avatar asked Apr 24 '19 15:04

Ogglas


1 Answers

The problem is that you swallow the error inside then, also you don't need multiple catches you only need one at the end like this:

fetch('api/specific/catalog/test')
    .then(response => {
        if (!response.ok) {
            return response.text().then(text => {
                throw new Error(`Request rejected with status ${response.status} and message ${text}`);
            })
        }
        else {
            return response.json()
        }
    })
    .then(data => {
        console.log(`OK: ${data}`);
    })
    .catch(error =>
        console.log(`Catch 3: ${error}`)
    );
like image 160
jcubic Avatar answered Nov 09 '22 13:11

jcubic