0

I'm trying to figure out the best way to handle the server error response promise

error.response.json();

without nesting it in the catch(). Is there a way this can be done outside of the catch and still only be called when there is an error?

return doGet(`/rest/hello-world`)
      .then(json => json.ListResponse)
      .then(result => {
        return dispatch({
          type: LOAD_SUCCESS,
          data: result.data,
        });
      })
      .catch(error =>
        error.response.json().then(result => {
          return dispatch({
            type: LOAD_FAIL,
            error: result.error.message,
          });
        })
      );

2 Answers2

0

Is there a way this can be done outside of the catch and still only be called when there is an error?

No.

I'm trying to figure out the best way to handle the server error response

It works quite a bit different, but I suspect what you actually wanted to write is

return doGet(`/rest/hello-world`)
      .then(json => ({
              type: LOAD_SUCCESS,
              data: json.ListResponse.data,
            }),
            error =>
              error.response.json().then(result => ({
                type: LOAD_FAIL,
                error: result.error.message,
              }))
      )
      .then(dispatch);

You might also want to consider the case that error.response.json() rejects on malformed responses.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • What is expected result of `error.response.json()`? Is that a bluebird specific syntax? – guest271314 Jul 28 '17 at 15:02
  • @guest271314 no, this has nothing to do with Bluebird. It's just the syntax that the OP used in his question; I don't know what `doGet` does exactly. – Bergi Jul 28 '17 at 15:06
  • _"I don't know what doGet does exactly."_ Where does `json` come from if not from a `Response.json()` call, as OP mentioned using `fetch()`? `Response` can only be read once, then `bodyUsed` flag is set to `true`. You could not then call `.json()` again within second parameter to `.then()` if the original `Response` object has been read and the `Response` object is not cloned and used for that call. – guest271314 Jul 28 '17 at 15:08
  • @guest271314 You'll have to ask someone who knows what `doGet` does. But it doesn't look like it would call `.json()` twice on the response. – Bergi Jul 28 '17 at 15:10
  • Your code calls `.json()` twice, else `json` at first `.then()` comes from where? – guest271314 Jul 28 '17 at 15:11
  • @guest271314 It comes from `doGet`, and I won't repeat that I don't know what it does internally. My code does use `error` in the same way as the code in the question, it's possible that there is a problem with the design of `doGet` but that's not what was asked about. – Bergi Jul 28 '17 at 15:14
  • 1
    `doGet` is just a custom function that calls `fetch()` and returns the response – KidsAndTheHall Jul 28 '17 at 15:14
  • Really do not care if you repeat yourself or not. Your code repeats itself where it is not possible to do so, that is self-evident. – guest271314 Jul 28 '17 at 15:15
  • @KidsAndTheHall The same `body` from `Response` cannot be read twice – guest271314 Jul 28 '17 at 15:16
  • @KidsAndTheHall you probably should put the `error.response.json()` call inside the `doGet` logic as well. That'll also reduce the nesting on the outside :-) Make sure to also generate appropriate errors (with a message?) when there is no response and `fetch` itself rejects. If you post your full code, possible as a [new question](https://stackoverflow.com/questions/ask), we can help you on that as well – Bergi Jul 28 '17 at 15:29
0

You can use Response.clone() to clone the Response and perform other tasks with the Response object

fetch("/url")
.then(response => {
  // do stuff with cloned `Response`
  const clone = response.clone();
  clone.json().catch(err => console.log(err));
  return response.json()
})
.then(json => /* do stuff */)
guest271314
  • 1
  • 15
  • 104
  • 177
  • [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) has no `catch` method. What is this code supposed to do, and what does it have to do with the question? Why do you think the response needs to be cloned? – Bergi Jul 28 '17 at 14:55
  • @Bergi `.json()` should have been chained to `clone` before `.catch()`, updated. The code clones the `Response` and handles network error separately from original `Response` – guest271314 Jul 28 '17 at 15:01
  • But why? a) you still use nested promise handlers and b) cloning makes absolutely no sense here, you could just as well have used `const x = response.json(); x.catch(…); return x;` – Bergi Jul 28 '17 at 15:04
  • @Bergi Well, your evaluation of what makes sense is your own. OP appears to want to handle `Response` separately from original `Promise` chain. – guest271314 Jul 28 '17 at 15:06