Will the second callback in then() be executed and why we need a throw statement?

Advertisements

I’m new to JavaScript and currently learning about Async JavaScript and HTTP Requests.

Here is the code that causes the confusion:

fetch(url, {
  method: "POST",
  headers: {
    "Content-type": "application/json",
    apikey: apiKey,
  },
  body: data,
})
  .then(
    (response) => {
      if (response.ok) {
        return response.json();
      }
      throw new Error("Request failed!");
    },
    (networkError) => {
      console.log(networkError.message);
    }
  )
  .then((jsonResponse) => {
    renderResponse(jsonResponse);
  });

Why is throw statement needed in the first callback in then(), since rejected case will be handled in the second callback?

I tried to ask chatgpt. It told me that when the program reaches the throw statement, then the second callback in then() will be executed, which made me more confused.

I appreciate it if someone could tell me the operating mechanism and the logic behind then() and its two callbacks.

>Solution :

When you pass two callbacks to .then() as in .then(fn1, fn2), then ONLY ONE of them will get executed based on the state of the parent promise. Throwing in fn1 will NOT cause fn2 to execute.

If you want your error handler to be executed when you throw in a .then() handler, then use a .catch() after it as in:

.then(fn1).catch(fn2)

In that case, throwing in fn1 will cause fn2 to execute.

Why is throw statement needed in the first callback in then(),

In your specific example, the throw is to turn the case when response.ok is not true into a promise rejection. fetch() by default only rejects when there’s an actual network error. A 400 or 500 status does not cause a rejection. As far as fetch() is concerned, any response from the server, even a 4xx or 5xx response is considered "success" and results in a resolved promise, not a rejection.

So, the point of your throw is to turn those 4xx and 5xx cases into a rejection. Of course, you don’t have any code in your example that will catch that rejection because you don’t show a subsequent .catch() or subsequent .then() with the second argument.

since rejected case will be handled in the second callback?

Your throw won’t be handle in your second callback. And, a !response.ok won’t be handled by your second callback either.


In my opinion, this whole issue of 4xx and 5xx responses not being a rejection is a primary benefit to using other libraries such as axios() or got() as it prevents you from having this extra code every time. Of course, you could also make your own wrapper utility function that you use instead of fetch(). In fact, I was bummed that nodejs was making the fetch() interface a standard interface because IMO this is a usability miss with the way this interface works. It leads to either faulty code when people don’t check and handle !response.ok or it results in extra code all the time to do so. Libraries like axios() or got() are configurable in this regard with a default to reject upon 4xx and 5xx response.

Leave a ReplyCancel reply