0

I'm trying to implement try/catch on javascript with Fetch API using PATCH Method. Most of the time when the fetch success I get a 400 (Bad Request) error and I don't know why, I wonder If I'm forgetting to add an if statement inside the try statement to check the response status before jumping into the catch statement. I also created a function called retry() to not allow the user to make more than 3 failing calls. And if I make it fail I am not able to see the numberOfRetries log updated.

const retry = async (callback, numberOfRetries) =>
  await callback(numberOfRetries)

export const updateValue = async (name, active, numberOfRetries = 0) => {
  try {
    await fetch(`${apiUrl}/device/${name}?active=${active}`, {
      method: 'PATCH',
      headers: {
        Accept: 'application/json',
        'Content-type': 'application/json; charset=UTF-8'
      },
      body: JSON.stringify({
        name,
        active
      })
    })
    console.log('ok')
  } catch (error) {
    if (numberOfRetries >= 2) {
      return
    }
    console.log(`retry number ${numberOfRetries}`)
    return await retry(updateValue, ++numberOfRetries)
  }
}

Console screenshot

enter image description here

Kaiser91
  • 333
  • 6
  • 17

1 Answers1

1

when the fetch is successfull I get a 400 (Bad Request) error and I don't know why, it's jumping into the catch statement.

No, the catch block doesn't run. The error you see in the devtools log is because a network request failed with an HTTP error code. You can disable the log messages in the console options.

As for why you are getting a 400 code, you have to check your serverside code - it suggests you are doing the request wrong.

I wonder If I'm forgetting to add an if statement inside the try statement to check the response status

Yes, you forgot that as well. You should check for the .ok property of the response:

export const updateValue = async (name, active, numberOfRetries = 0) => {
  try {
    const response = await fetch(`${apiUrl}/device/${name}?active=${active}`, {
//  ^^^^^^^^^^^^^^
      method: 'PATCH',
      headers: {
        Accept: 'application/json',
        'Content-type': 'application/json; charset=UTF-8'
      },
      body: JSON.stringify({
        name,
        active
      })
    })
    if (response.ok) {
//  ^^^^^^^^^^^^^^^^
      console.log('ok')
      // console.log(await response.text()) or something
    } else {
      throw new Error("HTTP Error "+response.status);
    }
  } catch (error) {
    if (numberOfRetries >= 2) {
      return
//    ^^^^^^ should be `throw error` instead of returning undefined?
    }
    console.log(`retry number ${numberOfRetries}`)
    return updateValue(name, active, ++numberOfRetries)
//                     ^^^^^^^^^^^^^ pretty surely you'll want to pass through the arguments
  }
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • check my edited response above and let me know what is your take – Meshack Mbuvi May 11 '19 at 18:10
  • @Bergi take a look at my code above I have a retry() function which accepts a callback in order to control the retries. I've tried your solution, but now when fails starts to throw lot of **PATCH device/1?active=undefined 400 (Bad Request)** errors in my console, like 3000 or more, you think should I use a setTimeOut to stop? also my CPU is getting overheat – Kaiser91 May 11 '19 at 18:32
  • @Kaiser91 The `retry` function that you posted does nothing but immediately call the "callback" with the single argument you gave it, I've inlined the whole thing for simplicity. But there's a mistake in your code, you will want to pass all three arguments. – Bergi May 11 '19 at 18:38
  • @Kaiser91 I've updated my answer to clarify. And yes, an infinite loop is to be expected when you pass the `numberOfRetries` in the wrong position so that it always takes the default of `0` in the recursive call. – Bergi May 11 '19 at 18:39
  • @Bergi yes you are right I was not passing the correct parameters to the function, now I get why this infinite loop, now It's working as expected – Kaiser91 May 11 '19 at 18:49