skip to Main Content

I have an API that will return data with a successful PATCH:

{
    "data": [
        {
            "id": 123456,
            "name": "Last, First",
            "pin": 55555,
            "status": 1,
        }
    ]
}

or an error:

{
"title": "Update failure",
"status": 400,
"errors": {
    "pin": [
        "The Driver PIN has already been taken."
    ],
    "status": [
        "The selected Status is invalid."
    ]
},
"detail": "Bad Request"

}

I’d like to be able to use the errors object to handle the exceptions in the calling function.

Currently, the function that does the modification includes this:

...

return fetch(url, options)
  .then((response) => {
    return response.json();
  })
  .then((data) => {
    return data;
  });

...

This will correctly return the success or failure’s JSON, but I’d like to throw an exception on failure (with the errors object).

What’s the recommended way to do this? Add a test for data.status in the second .then and throw an error with the data?

3

Answers


  1. The best way would be to first check the http status code by checking the status property on the response object
    Something like:

    if(response.status != 200) {
       //Do some error handling by using the errors array in the response.
    }
    

    This is assuming that the API returns appropriate http status codes (401 for unauthorized, 400 for bad request, 500 for internal server error, etc.)
    This will help if the API does not always return proper JSON structure in case of an error.

    Otherwise, your best bet would simply be to check for status field.

    Login or Signup to reply.
  2. Add a test for data.status in the second .then and throw an error with the data?

    Yes! That’s the best way to throw an exception in this case.

    I would probably create a cusom error class, so you can easly check if the catched error was throwed by you or the fetch call itself, and you can handle it in the right way.

    So, create a custom error class:

    class MyError extends Error {  
        constructor (message, data) {
          super(message)
      
          this.name = this.constructor.name
      
          // capturing the stack trace keeps the reference to your error class
          Error.captureStackTrace(this, this.constructor);
      
          // you may also assign additional properties to your error
          this.data = data
        }
    }
    

    Now you can use your custom error class in your code

    return fetch(url, options)
      .then((response) => {
        return response.json()
      })
      .then((data) => {
        if (data.status !== 200)
           throw new MyError('Validation Error', data.errors)
        
        return data;
      })
      .catch(e => {
        if (e.name === 'MyError') { // OR if (e istanceof MyError)
          // here you know the error was thrown by you. Now you can handle it
          // e.name -> 'MyError'
          // e.message -> 'Validation Error'
          // e.data -> the data.errors object
        } else {
          // if you reach this path, some error thrown by the fetch API happened
        }
      })
    

    Note that the Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.

    For better readability, I would suggest the usage of async/await

    try {
       const response = await fetch(url, options)
       const data = await response.json()
       if (data.status !== 200)
          throw new MyError('Validation Error', data.errors)
       // Here everything is ok!
    } catch(e) {
       if (e.name === 'MyError') { // OR if (e istanceof MyError)
          // here you know the error was thrown by you. Now you can handle it
          // e.name -> 'MyError'
          // e.message -> 'Validation Error'
          // e.data -> the data.errors object
        } else {
          // if you reach this path, some error thrown by the fetch API happened
        }
    }
    
    Login or Signup to reply.
  3. You should check the response before getting json.
    For example:

    return fetch(url, options)
      .then((response) => {
        if(response.ok)
          return response.json();
        else throw response.json();
      })
      .then((data) => {
        return data;
      }).catch((error) => {/* handle error */});
    

    Here more https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#checking_that_the_fetch_was_successful

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search