2

Sometimes I find myself writing the following code:

if (result.status == 200) {
    return result.json()
} else {
    return result.json().then(res => Promise.reject(res))
}

If the status is any other than 200 then the result will contain an error message which I would like to return. (This is part of a api.js script)

Is there a better way to "inverse" the .json() promise?

I thought of maybe something like this:

return Promise.reject(result.json)

Is there a way for me to do something like that? I am expecting the successful result of result.json to be the error object in the catch route.

ThatBrianDude
  • 2,952
  • 3
  • 16
  • 42
  • If `result` is always JSON, why not process it first and then reject the promise? – 31piy May 09 '18 at 14:18
  • "Is there a way for me to do something like that?" Have you tried doing it that way? How so and what was the result? – chevybow May 09 '18 at 14:19
  • 1
    Yes, it seems the promise resolves anyway since Promise.reject is returning a resolved promise. I tested it like so: const test = () => Promise.reject(() => Promise.resolve("yay")) – ThatBrianDude May 09 '18 at 14:22

2 Answers2

1

Well this looks a little weird, I would go with this approach

return result.json().then(json => {
   if (result.status === 200) {
      return json;
   }

   throw new Error(`Failed with ${json}`);
});
  • You should always throw/return rejected promises with Error objects inside. Some modules are even counting on that and can behave unexpectably with throwing non-error object
  • I think the throwing error is more "obvious" then returning something that behaves as throwing error
  • if-else is increasing complexity. Remove else if not necessary
  • It is better to get used to ===, using == can bring some issues
libik
  • 22,239
  • 9
  • 44
  • 87
  • 1
    I think you meant `return json;`. This makes a lot of sense I will use this approach. The problem I see with returning an error object is that I already built an "error" object on the server side. Its just a json object but it contains the message and a code. I certainly shouldnt send over an actual error object? This makes me just return the result json in case of an error since it has all the information needed. – ThatBrianDude May 09 '18 at 14:29
  • And about the == vs === I am aware of the difference, I am usually just unsure if the fetch library I am using returnes a string or number as the statuscode. I think in this case its safe to use == – ThatBrianDude May 09 '18 at 14:32
  • @ThatBrianDude no, if it's spec conforming it will be an integer. Although you are correct that it is safe in this case, it's not worth the noise from the linter. – Jared Smith May 09 '18 at 14:35
  • 1
    Great to know theres a spec for that. Noted. You might still want to edit the return value though ;) – ThatBrianDude May 09 '18 at 14:45
  • `json => result.status === 200 ? json : Promise.reject(json)` – Patrick Roberts May 09 '18 at 14:46
  • 1
    @ThatBrianDude - If you are throwing an error, you should return an error. You can use custom errors, but they should extend the Error class. Also you should NOT use returning rejecting promise as workaround to return value differently. It is same as throwing error and should be handled as error. If you want to handle it as part of non-error standard business logic, you should return something like `{valid: true, json: '...'}` – libik May 09 '18 at 15:00
0
return result.json().then(res=>{
  if(result.state!==200) return Promise.reject(res);
  return res;
});

In my case I prefer the Promise.reject

info: Promise.reject vs throw Error

fifoq
  • 183
  • 13