Fetch api - getting json body in both then and catch blocks for separate status codes
<p>I am using fetch api for fetching an URL that might return:</p>

<blockquote>
  <p>Response : status = 200, json body = {'user': 'abc', 'id': 1}</p>
</blockquote>

<p>or</p>

<blockquote>
  <p>Response : status = 400 , json body = {'reason': 'some reason'}</p>
</blockquote>

<p>or </p>

<blockquote>
  <p>Response : status = 400 , json body = {'reason': 'some other reason'}</p>
</blockquote>

<p>I want to make a separate function <code>request()</code> that I use from various parts of my code as follows:</p>

<pre><code>    request('http://api.example.com/').then(
        // status 200 comes here
        data =&gt; // do something with data.id, data.user
    ).catch(
        // status 400, 500 comes here
        error =&gt;  // here error.reason will give me further info, i also want to know whether status was 400 or 500 etc
    )
</code></pre>

<p>I am unable to do the split between 200 and 400,500 (i have tried by throwing an error). When I throw an error, I am finding it hard to still extract the JSON body (to use for error.reason). </p>

<p>My current code is as follows:</p>

<pre><code>import 'whatwg-fetch';

/**
 * Requests a URL, returning a promise
 */
export default function request(url, options={}) {

    console.log('sending api request, url = ' + url)

    return fetch(url, options)
        .then(checkStatus)
        .then(parseJSON)
        .then((data) =&gt; ({data}))
        .catch((err) =&gt; ({err}));
}


function checkStatus(response) {
    if (response.status &gt;= 200 &amp;&amp; response.status &lt; 300) {
        return response;
    }

    const error = new Error(response.statusText);
    error.response = response;
    throw error;
}



function parseJSON(response) {
    return response.json();   // json() is a promise itself
}
</code></pre>

<p>I have tried to solve this by doing as follows, by inverting the order of <code>.then()</code> calls, but does not work</p>

<pre><code>export default function request(url, options) {
    return fetch(url, options)
        .then(parseJSON)        // note that now first calling parseJSON to get not just JSON but also status. 
        .then(checkStatus)      // i.e. Inverted order of the two functions from before

        .then((data) =&gt; ({data}))
        .catch((err) =&gt; ({err}));
}

function checkStatus({data, status}) {

    if (status &gt;= 200 &amp;&amp; status &lt; 300) {
        return data;
    }
    else {
        // const error = new Error(response.statusText);
        const error = new Error("Something went wrong");
        // error.response = response;
        error.data = data;

        throw error;
    }

}

function parseJSON(response) {
    let jsonBody

    response.json().then(json =&gt; {
        jsonBody = json                 // this does not help, i thought it will make jsonBody fill up, but seems its in a diff thread
    })              

    return {
        data: jsonBody,
        status: response.status     // my aim is to send a whole dict with status and data to send it to checkStatus, but this does not work
    }
}
</code></pre>