简体   繁体   中英

Fetch API error handling

I want to display error message from my API, problem is that I can't reach that error if I check for response.ok , it returns Fetch error, not the one from API..

If I don't use if(response.ok)... it returns the error from API but it dispatches the success action.

Here is the example, login action:

 export const signIn = data => dispatch => { dispatch({ type: SIGN_IN }) fetch(API_URL+'/login', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(data), }) .then( response => { if (!response.ok) { throw response } return response.json() //we only get here if there is no error }) .then( json => { dispatch({ type: SIGN_IN_SUCCESS, payload: json }), localStorage.setItem("token", 'Bearer '+json.token) localStorage.setItem("user", JSON.stringify(json.user)) }) .catch( err => { dispatch({ type: SIGN_IN_FAILED, payload: err }) }) }

This is the code for action that dispatches the right message but as success action, not as failed one..

 export const signIn = data => dispatch => { dispatch({ type: SIGN_IN }) fetch(API_URL+'/login', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(data), }) .then( response => response.json()) .then( json => { dispatch({ type: SIGN_IN_SUCCESS, payload: json }), localStorage.setItem("token", 'Bearer '+json.token) localStorage.setItem("user", JSON.stringify(json.user)) }) .catch( err => { dispatch({ type: SIGN_IN_FAILED, payload: err }) }) }

according to This Article :

Per MDN , the fetch() API only rejects a promise when

“a network error is encountered, although this usually means permissions issues or similar.”

Basically fetch() will only reject a promise if the user is offline, or some unlikely networking error occurs, such a DNS lookup failure.

then, you can use this part of code to use non-network error handlings and make your code more readable

function handleErrors(response) {
    if (!response.ok) throw new Error(response.status);
    return response;
}

fetch("API URL")
    // handle network err/success
    .then(handleErrors)
    // use response of network on fetch Promise resolve
    .then(response => console.log("ok") )
    // handle fetch Promise error
    .catch(error => console.log(error) );

In order to extract API message from server in case of some error, you have to use the following idiom (which doesn't lie on the surface though), see link

     fetch("http://localhost:8090/test/error", {
        method: 'GET',
        headers: {
            'Accept': 'application/json'
        }
    })
        .then(result => {
            //Here body is not ready yet, throw promise
            if (!result.ok) throw result;
            return result.json();
        })
        .then(result => {
            //Successful request processing
            console.log(result);
        }).catch(error => {
            //Here is still promise
            console.log(error);
            error.json().then((body) => {
                //Here is already the payload from API
                console.log(body);
            });
        })

Verbose - yes!, but does exactly what is needed.

With the following solution one can handle JSON API error, Generic API error and Generic fetch error

fetch("api/v1/demo", {
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        "data": "demo"
    })
})
    .then(response => {
        if (!response.ok) {
            return Promise.reject(response);
        }
        return response.json();
    })
    .then(data => {
        console.log("Success");
        console.log(data);
    })
    .catch(error => {
        if (typeof error.json === "function") {
            error.json().then(jsonError => {
                console.log("Json error from API");
                console.log(jsonError);
            }).catch(genericError => {
                console.log("Generic error from API");
                console.log(error.statusText);
            });
        } else {
            console.log("Fetch error");
            console.log(error);
        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM