Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle response .json and .text using fetch?

I'm fetching an API that returns a json but when it has an error, it returns only a text (In node with express, results are returned with .json({}) and errors with .send('string')), but I can't modify the API

So I'm trying to make something that reads the json, but if it's an text, it will go in .catch where the error is the text.

Here is what I have tried but with no success.

fetch(apiUrl)
    .then(res => {
        try {
            let json = res.json()
            return json
        } catch (error) {
            return new Promise((resolve, reject) => reject(res.text()))
        }
    })
    .then(res => {
        // get result from res.json() **res == res.json**
    })
    .catch(error => {
        // get result from res.text() **res == res.text**
    })

How can I achieve this? How to get res.json() in the next .then() but if it fails, get res.text() in the .catch?

Edit:

I want to get the .text in .catch. I don't know why, but throwing res.text() doesn't work.

like image 829
Vencovsky Avatar asked May 20 '19 19:05

Vencovsky


People also ask

How do I get JSON from fetch response?

To get JSON from the server using the Fetch API, you can use the response. json() method. The response. json() method reads the data returned by the server and returns a promise that resolves with a JSON object.

How do I fetch data from a JSON file?

The jQuery code uses getJSON() method to fetch the data from the file's location using an AJAX HTTP GET request. It takes two arguments. One is the location of the JSON file and the other is the function containing the JSON data. The each() function is used to iterate through all the objects in the array.

How do I get a response object from Fetch?

The Fetch API allows you to asynchronously request for a resource. Use the fetch() method to return a promise that resolves into a Response object. To get the actual data, you call one of the methods of the Response object e.g., text() or json() . These methods resolve into the actual data.

How do I send JSON data using fetch API?

POST request using fetch API:To do a POST request we need to specify additional parameters with the request such as method, headers, etc. In this example, we'll do a POST request on the same JSONPlaceholder and add a post in the posts. It'll then return the same post content with an ID.


2 Answers

Another approach would be to simply format eveyrthing to text initially and only then try to parse it, while throwing an error in case of parsing issues.

fetch("http://maps.googleapis.com/maps/api/geocode/json?address=google")
    .then(res => res.text())
    .then(body => {
        try {
            return JSON.parse(body);
        } catch {
            throw Error(body);
        }
    })
    .then(console.log)
    .catch(console.error);

fetch("http://maps.googleapis.com/maps/api/geocode/xml?address=google")
    .then(res => res.text())
    .then(body => {
        try {
            return JSON.parse(body);
        } catch {
            throw Error(body);
        }
    })
    .then(console.log)
    .catch(console.error);
like image 71
Krzysztof Krzeszewski Avatar answered Sep 21 '22 15:09

Krzysztof Krzeszewski


Ideally, your client application should know what response kind to expect and have static code that calls the appropriate method.


Another way to deal with your situation is to inspect the response contentType and call .json() or .text() depending on particular response header value.

handleResponseStatusAndContentType(response) {
  const contentType = response.headers.get('content-type')!;

  if (response.status === 401) throw new Error('Request was not authorized.');

  if (contentType === null) return Promise.resolve(null);
  else if (contentType.startsWith('application/json;')) return response.json();
  else if (contentType.startsWith('text/plain;')) return response.text();
  else throw new Error(`Unsupported response content-type: ${contentType}`);
}

Usage:

return fetch(
  url,
  requestInit,
)
.then(response => handleResponseStatusAndContentType(response))
.catch(error => {
  console.error(error);
  return error;
});
like image 43
Igor Soloydenko Avatar answered Sep 20 '22 15:09

Igor Soloydenko