javascriptfetch-apicatch-block

fetch() not catching custom error message


I have the following fetch() api but the catch blocks aren't working correctly. The error message I get is:

SyntaxError: Unexpected token < in JSON at position 0 undefined

but what I'm expecting is:

something went wrong null

here's the api:

const getBtn = document.getElementById('get-btn')
const postBtn = document.getElementById('post-btn')


const sendHttpRequest = (method, url, data) => {
    return fetch(url, {
        method: method,
        body: JSON.stringify(data),
        headers: data ? {'Content-Type': 'application/json'} : {}
    })
        .then(response => {
            console.log(response.status)
            if(response.status >= 400 || response == null){
                return response.json()
                    .then(errResData => {
                        const error = new Error('something went wrong')
                        error.data = errResData
                        throw error;
                    })
            }
            return response.json()
    })
}

const getData = () =>{
    sendHttpRequest('GET','http://localhost/async/fetch/data.jsonx')
        .then(responseData => {
            console.log(responseData)
        })
        .catch(err =>{
            console.log(err,err.data)
        })

}

const sendData = () =>{
    sendHttpRequest('POST','http://localhost/async/fetch/data.phpx',{
        email: 'someemail@gmail.com',
        password: 'compas'
    })
        .then(responseData => {
            console.log(responseData)
        })
        .catch(err => {
            console.log(err,err.data)
        })
}


getBtn.addEventListener('click',getData)
postBtn.addEventListener('click',sendData)

Solution

  • In order to see if a body is parseable as JSON, you need to call .json on the Promise. That will return a Promise that either resolves to the parsed value, or will throw due to the body not being parseable.

    If it isn't parseable, .thens connected to it won't run; return response.json().then will not work if the body isn't parseable, so the interpreter never gets to new Error('something went wrong').

    .then(response => {
        console.log(response.status)
        if(response.status >= 400 || response == null){
            return response.json()
                .then(errResData => {
                    const error = new Error('something went wrong')
                    error.data = errResData
                    throw error;
                })
        }
        return response.json()
    

    should be

    .then(response => {
        console.log(response.status)
        if(response.status >= 400 || response == null){
            return response.json()
                .catch(errResData => {
                    const error = new Error('something went wrong')
                    error.data = errResData
                    throw error;
                })
        }
        return response.json()
    

    if the non-parseable response will always fulfill the condition response.status >= 400 || response == null.

    The throw error inside the .catch in the edited code will result in the Promise rejecting, so getData's .catch will see the error.