Using Fetch API to Access JSON - javascript

I am trying to use fetch api to bring back some data, however am unable to map it to the console once I have retrieved it.
fetch('http://jsonplaceholder.typicode.com/users', {
method: 'GET'
}).then(function(response) {
console.log(response)
response.forEach(i => console.log(i.name));
}).catch(function(err) {
console.log(`Error: ${err}` )
});
The error i get is
response.map is not a function
so I tried to parse the response,(ie var data=JSON.parse) which did not work, with the error
SyntaxError: Unexpected token o in JSON at position 1"
Interestingly, when doing the same thing with a XMLHttp request, I was required to parse it, so I would also be interested to know why the difference between these two methods of retrieving the data.
If anyone could point me in the right direction, I would be really grateful.

The Fetch API returns a response stream in the promise. The response stream is not JSON, so trying to call JSON.parse on it will fail. To correctly parse a JSON response, you'll need to use the response.json function. This returns a promise so you can continue the chain.
fetch('http://jsonplaceholder.typicode.com/users', {
method: 'GET'
})
.then(function(response) { return response.json(); })
.then(function(json) {
// use the json
});

Understanding promises is key to using the fetch API.
At the time you're trying to parse your response and loop through it, the response is actually just a promise. In order to utilize the contents of the actual response from the request, you'll have to do some promise chaining.
fetch('http://jsonplaceholder.typicode.com/users').then(function(response) {
// response.json() returns a promise, use the same .then syntax to work with the results
response.json().then(function(users){
// users is now our actual variable parsed from the json, so we can use it
users.forEach(function(user){
console.log(user.name)
});
});
}).catch(err => console.error(err));

It appears that you might be accessing the json incorrectly. You could try calling response.json() instead.
fetch('http://jsonplaceholder.typicode.com/users', {
method: 'GET'
}).then((response) => {
response.json().then((jsonResponse) => {
console.log(jsonResponse)
})
// assuming your json object is wrapped in an array
response.json().then(i => i.forEach(i => console.log(i.name)))
}).catch((err) => {
console.log(`Error: ${err}` )
});
This example is structured to match your example, but ideally, you would return response.json() on that first .then block and proceed on the next block. Here is a similar example that proceeds on the next block.
In your particular case, you can view the Fetch API as a json aware wrapper for "XMLHttpRequest"s. Main differences being that the Fetch API is simpler, functional-like, and has convenience methods. David Walsh does a reasonable comparison in his blog post, which I recommend you take a look at. Plain "XMLHttpRequest"s just pass you whatever string was sent back from the server, it has no idea it could be JSON, and thus leaves it to the user to parse the response whatever way they see fit.

Related

"TypeError: response.json is not a function" when trying to parse json

I am getting an error I do not understand. I'm fetching an API url in json format, followed by a json to JS object parsing, using json()
const response = fetch('https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020');
const data = response.json();
Can someone please explain this error..
fetch is an asynchronous function; it doesn't return the response right away (you get a Promise instead).
If you want to fetch the data, you need to use the await (if the fetch is called inside another async function), or provide a callback via then method in the Promise from the fetch call:
fetch('https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020')
.then(response => {
const data = response.json();
});
Working with data from response
If you would do something like this, it won't work:
let data;
fetch('https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020')
.then(response => {
data = response.json();
});
console.log(data);
The reason is because the callback inside the then method is executed after the response has been returned (this might take seconds for example), but the console.log(data) is executed immediately after the fetch is called. This means that the data isn't assigned yet and will be probably undefined. For this reason, if you want to put data somewhere, you need to put your code inside the callback.
function processData(responseData) {
// Here, you can put your code to process the data from response
console.log(responseData);
}
fetch('https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020')
.then(response => {
const data = response.json();
processData(data);
});
This way the data will be processed after it is fetched.
Fetch returns a Promise since you are sending a request to an API. This type of functions is asynchronous since we don't know when we're getting back the response from the API.
You can either use async/await or .then() and .catch() to execute your code when you get back the response.
Try this:
let returnedData;
fetch('https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020')
.then((data) => {
console.log(data)
returnedData = data
})
.catch((error) => {
console.log(error)
})

JSON.parse() Vs. .json()

I have been working with fetch API and Promises recently and I came across .json() . Oftentimes .json() returns the same output as JSON.parse. I googled the question and the results pointed in other directions.
Example with XHR and JSON.parse:
$('#xhr').click(function(){
var XHR = new XMLHttpRequest();
XHR.onreadystatechange = function(){
if (XHR.status == 200 && XHR.readyState == 4) {
$('#quote').text(JSON.parse(XHR.responseText)[0]);
}
};
XHR.open("GET", url);
XHR.send();
});
Example with Fetch API:
$('#fetch').click(function(){
fetch(url)
.then(function(res){
return res.json();
})
.then(function(quote){
$('#quote').text(quote);
})
.catch(function(err){
handleError(err);
});
});
Could someone please explain the difference between these seemingly similar concepts ?
Thanks
Body.json() is asynchronous and returns a Promise object that resolves to a JavaScript object. JSON.parse() is synchronous can parse a string and change the resulting returned JavaScript object.
'AJAX' works with 'callbacks';
'fetch' works with 'promises'.
Use JSON.parse() to parse the response for AJAX.
Use json() to parse the response for fetch.
In my view both res.json and JSON.parse do the same functioning. Preference to res.json is given because of it's syntax.
Sharing the example for better understanding...
this.service.userFunction() //calling service
.then((res) => {
this.userdetails = JSON.parse(res._body); //use this
this.userdetails = res.json(); // or use this syntax any one
)}
.catch()
Using any of one them will provide the the complete response body and understanding of their functionality.
The json() method of the Body mixin takes a Response stream and reads it to completion. It returns a promise that resolves with the result of parsing the body text as JSON.
The JSON.parse() method parses a JSON string, constructing the JavaScript value or object described by the string.
Use JSON.parse() to parse the response for AJAX. Use json() to parse the response for fetch.

Why can't I view json inside fetch's Response object in the developer console?

I recently learned about JavaScript's Fetch API, and am wondering why I cannot see json data directly from the Response object returned from the Fetch.
For example, I have a url that returns some json.
fetch("https://myURL/json",
{
method: "GET",
credentials: "include"
}
)
.then(function(response) {
if(response.ok) {
return response.json();
}
throw new Error('Network response was not ok.');
}).then(function(myJson) {
console.log(myJson);
})
If I put a breakpoint inside the first .then, I can view the Response object returned from the fetch in Chrome/Firefox's developer console. That object will have some data, but no way to directly view the json. I have to call that object's .json() method and return that to actually see the json data.
Why can't I see the json data inside the Response object before calling .json()? Hasn't the Fetch finished when we reach the first .then()?
according to this google developers article
The response of a fetch() request is a Stream object, which means that when we call the json() method, a Promise is returned since the reading of the stream will happen asynchronously.
MDN has some info on this as well
I don't know if you made a mistake while copy-pasting your code, but you are missing the closing quotes on the URL string.
Besides that, I tried that snippet of code and it does what it is supposed to do:
fetch("https://jsonplaceholder.typicode.com/users", {
method: "GET",
credentials: "include"
})
.then(function(response) {
if (response.ok) {
return response.json();
}
throw new Error('Network response was not ok.');
}).then(function(myJson) {
console.log(myJson);
});
https://jsfiddle.net/9s9t2968/

YQL fetch returns empty object

I'm trying to retrieve json from a domain which don't allow CORS and I don't have access to the server to allow it. I have replaced the url with googleapis as an example here.
const url = 'https://www.googleapis.com/storage/v1/b/example-bucket/o/foo%2f%3fbar';
const yUrl = 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%3D%22' + encodeURIComponent(url) + '%22&format=json';
fetch(yUrl)
.then(function(response){
alert(JSON.stringify(response, null, 4));
})
If we open the yUrl in browser itself, it works fine: http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%3D%22https%3A%2F%2Fwww.googleapis.com%2Fstorage%2Fv1%2Fb%2Fexample-bucket%2Fo%2Ffoo%252f%253fbar%22&format=json
However the response alerted (and thus returned) to fetch is empty.
Kindly guide me in the right direction. Thanks.
P.S. I don't want to use jQuery, would prefer JavaScript.
A fetch(…) call returns a promise containing a response object, and to get the JSON from that, you need to use the .json() method, which returns a promise containing the JSON.
So all together to see the serialized JSON data, you need to do something like this:
fetch(yUrl)
.then(response => response.json())
.then(json => JSON.stringify(json))
.then(function(json) {
alert(json);
})

How to get data out of a fetch request

I've been trying to move from XHR to fetch. When I make a GET request, I can't figure out how to get data out of the response, all I get is more promise objects that still don't contain any data. I just want the data as a string.
UPDATE: my code so far isn't much to speak of:
fetch(URL)
.then(function(response) {
console.log(response);
return response;
});
...where URL is the URL of an API that returns some data as JSON

Categories

Resources