How to Store Fetch API JSON Response in a JavaScript Object - javascript

I want to store a Fetch API JSON as a JavaScript object, so I can use it elsewhere. The console.log test works, but I can't access the data.
The Following Works: It shows console entries with three to-do items:
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => console.log(success));
The Following Does Not Work:
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => JSON.parse(success));
If I try to access success, it does not contain any data.
Have tried console.log, which works.
Have also tried the following, which works:
fetch('http://localhost:3000/api/todos')
.then(res => res.json())
.then(data => {
let output = '';
data.forEach(function (todo) {
output += `
<ul>
<li>ID: ${todo.id}</li>
<li>Title: ${todo.title}</li>
<li>IsDone: ${todo.isdone}</li>
</ul>
`;
});
document.getElementById('ToDoList').innerHTML = output;
return output;
})
.catch(err => console.log('Something went wrong: ', err));
However, I can't manually update inner HTML; I need the object to do other UX.

You can also use a function like below:
function doSomething(success){
//do whatever you like
}
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => doSomething(success));

You can just declare a variable outside and assign your result to it like this
var yourTodos;
fetch('http://localhost:3000/api/todos')
.then(data => data.json())
.then(success => yourTodos = success);
Then you have the yourTodos as your javascript object that you can use whatever you want.

You can use async await like below
async function consumingFunc () {
let response = await fetch('http://localhost:3000/api/todos')
console.log(response)
}
consumingFunc()

Related

Display images on the browser with map method using url's coming from an API

I'm trying to display two images on the browser based on url's I got from an API.
So,
I have fetched the data
run a map method that will run all over the array that I got, and whenever it running into an image it inserts it into a empty div using innerHTML.
and this is what i got:
HTML:
<body>
<button id="new-deck">New Deck, Please!</button>
<button id="draw-cards">Draw</button>
<script src="index.js"></script>
<div id="container-card"></div>
</body>
JS:
let deckId
let container = document.getElementById('container-card')
function handleClick() {
fetch("https://deckofcardsapi.com/api/deck/new/shuffle/?deck_count=1")
.then(res => res.json())
.then(data => {
console.log(data)
deckId = data.deck_id
})
}
document.getElementById("new-deck").addEventListener("click", handleClick)
document.getElementById("draw-cards").addEventListener("click", () => {
fetch(`https://deckofcardsapi.com/api/deck/${deckId}/draw/?count=2`)
.then(res => res.json())
.then(data => data.cards.map(item =>container.innerHTML += `<img src=${item.image}/>`))
})
There are two issues:
you are not submitting deckId during image fetch api call.
image src url must be enclosed into quotes, otherwise backslash is added to the end of the url:
let deckId
let container = document.getElementById('container-card')
function handleClick() {
fetch("https://deckofcardsapi.com/api/deck/new/shuffle/?deck_count=1")
.then(res => res.json())
.then(data => {
console.log(data)
deckId = data.deck_id
})
}
document.getElementById("new-deck").addEventListener("click", handleClick)
document.getElementById("draw-cards").addEventListener("click", () => {
fetch(`https://deckofcardsapi.com/api/deck/${deckId}/draw/?count=2`)
.then(res => res.json())
.then(data => data.cards.map(item =>container.innerHTML += `<img src="${item.image}"/>`))
})
<button id="new-deck">New Deck, Please!</button>
<button id="draw-cards">Draw</button>
<script src="index.js"></script>
<div id="container-card"></div>
Every time you are dealing with API calls, make sure you check what data you receive before you minimalistic your code with one-liners.
and use catch for promises to catch any errors that might occur.

Trouble with fetch error handling in Reactjs

I'm learning how to use fetch and was trying the following syntax:
const [stuff, setStuff] = useState([]);
const request = "link-to-API";
const data = await fetch(request)
.then(response => response.json())
.catch(err => {
console.log(err);
return {} //(or [], or an empty return, or any return at all)
})
setStuff(data.hits)
Then, in the return, I have:
{stuff.map((element) => (
<Thing
title={element.label}
link={element.url}
/>
))}
Thinking I could just render an empty object whenever my fetch fails. Except, this works only when the fetch itself works. React gives me the error
"Objects are not valid as a React child (found: TypeError: Failed to
fetch)."
But I can't find any solution online. How could I handle the errors just by not rendering anything?
(that's not the only part I'm rendering, I just want to render an empty div, not conditionally render that part)
when you use await you can't use then and catch methods
It's important that you use await in async function
let data = null
try{
const response = await fetch(request)
data = response.json();
} catch(err) {
console.log(err);
}
you can try removing the await keyword, as you are using .then
also the datafetching part should be included inside useEffect
const [stuff, setStuff] = useState([]);
const request = "link-to-API";
useEffect( ()=> {
fetch(request)
.then(response => response.json())
.then(data => setStuff(data.hits))
.catch(err => {console.log(err)})
},[])

How control javascript error when json is empty

I am parsing a JSON file in javascript. Every 5 minutes the JSON is autoimatically updated with new data, during the time it is being updated the JSON is blank (for a about 2 seconds).
I get this error
Uncaught (in promise) SyntaxError: Unexpected end of JSON input
at fetch.then.res
This is the code in javascript for parsing the JSON:
fetch("http://location/file/data.json")
.then(res => res.json())
.then(data => {
//do something
})
How do I control this so that it doesn't flag this error? I still want an a customer error to appear using console.log(Error()).
Any help is appreciated.
This should do the trick. then() takes a second callback function as argument that receives the error object.
fetch("http://location/file/data.json")
.then(res => res.json(), err => console.log(err))
.then(data => {
//do something
}, err => console.log(err))
EDIT: As per comment, this way is preferred. Can read more about using promises in this link
fetch("http://location/file/data.json")
.then(res => res.json())
.then(data => {
//do something
})
.catch(err => console.log(err)
You can add .catch into your processing:
fetch("http://location/file/data.json")
.then(res => res.json())
.then(data => {
// do something
})
.catch(err => console.log(err.message))
EDIT: err.message instead of JSON.stringify(err).

Need guidance! Trying to learn about fetch() and Promises

Basically I'm trying to fetch the URL and URLPaths for two images I've uploaded (to Firebase) using the firebase function /storeImage and JSON.Stringify().
Below is the snippet of code that enables me to fetch data for the ONE image.
.then(token => {
authToken = token;
return fetch("myappURL/storeImage",
{
method: "POST",
body: JSON.stringify({
image: image.base64
}),
headers: {
Authorization: "Bearer " + authToken,
}
});
})
.catch(err => {
console.log(err);
alert("Oops! Something went wrong, please try again1")
dispatch(uiStopLoading());
})
.then(res => {
if (res.ok) {
return res.json();
} else {
throw(new Error());
}
})
.then(parsedRes => {console.log(parsedRes);
Now I want to fetch data from a second image.
What I gather, from the docs I've read, is that I should use promises for multiple async calls like what I have above. So, shouldn't something like this (see below) work?
.then(token => {
authToken = token;
let image = fetch(... image: image.base64 ...);
let coverImage = fetch(... coverImage: coverImage.base64 ...);
Promise.all([image, coverImage])
.then(ress => { ress.forEach(
res => {
process( res.json() );
})
})
.catch(err => {...})
.then(res => {...})
.then(parsedRes => {console.log(parsedRes);)
Spoiler alert. I tried and it didn't. But I cannot understand why.
When you chain promises together, that is, start a new promise inside a then callback you need to return it.
Promise.all returns a single new promise that resolves when all of the promises passed to it resolve. In your code above you're neglecting to return it.
E.g. Try running this code which logs undefined
Promise.resolve()
.then(() => {
Promise.all([Promise.resolve(1), Promise.resolve(2)])
})
.then(result => console.log(result))
vs this code which logs [1, 2]
Promise.resolve()
.then(() => {
return Promise.all([Promise.resolve(1), Promise.resolve(2)])
})
.then(result => console.log(result))

Javascript Fetch API - How to save output to variable as an Object (not the Promise)

Please, how can I save output of fetch to a variable - to be able to work with it as with an object?
Here is the code:
var obj;
fetch("url", {
method: "POST",
body: JSON.stringify({
"filterParameters": {
"id": 12345678
}
}),
headers: {"content-type": "application/json"},
//credentials: 'include'
})
.then(res => res.json())
.then(console.log)
The final console.log will show an object. But when I tried to save it to variable .then(res => obj = res.json()) than the console.log(obj) will not hold the Object, but the Promise.
Any idea please, how to turn it into an Object saved in the variable?
.json() is an async method (it returns a Promise itself), so you have to assign the parsed value in the next .then()
var obj;
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(res => res.json())
.then(data => {
obj = data;
})
.then(() => {
console.log(obj);
});
Modern async/await equivalent
You have to await the .json() method.
async function foo() {
let obj;
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1')
obj = await res.json();
console.log(obj)
}
foo();
Instead of storing in a variable, create a function that will return data, and then store it in a variable. So It can accessible in your whole file.
async function fetchExam(id) {
try {
const response = await fetch(`/api/exams/${id}`, {
method: 'GET',
credentials: 'same-origin'
});
const exam = await response.json();
return exam;
} catch (error) {
console.error(error);
}
}
Then call that function to get data
async function renderExam(id) {
const exam = await fetchExam(id);
console.log(exam);
}
Update
With the current version of Node.js v14.3.0 support Top-Level async-await
import axios from 'axios';
const response = await axios('https://quote-garden.herokuapp.com/api/v3/quotes/random');
console.log(response.data);
Running this file using node --harmony-top-level-await top-level-async-await.js
Output
More details: https://medium.com/#pprathameshmore/top-level-await-support-in-node-js-v14-3-0-8af4f4a4d478
You can do like this. First fetch the data and create a function to do something with the data.
And then pass the result to that function and access it anywhere.
fetch('https://pokeapi.co/api/v2/pokemon/ditto')
.then(jsonData => jsonData.json())
.then(data => printIt(data))
let printIt = (data) => {
console.info(typeof data)
}
let data = [];
async function getRandomUser(){
// gets the response from the api and put it inside a constant
const response = await fetch('https://randomuser.me/api');
//the response have to be converted to json type file, so it can be used
const data = await response.json();
//the addData adds the object "data" to an array
addData(data)
}
function addData(object) {
// the push method add a new item to an array
// here it will be adding the object from the function getRandomUser each time it is called
data.push(object);
//the fetched data is available only on this scope
console.log("This is the value of date inside the function addData:")
console.log(data)
}
//Calls the function that fetches the data
getRandomUser()
console.log("This is the value of data outside the scope")
console.log(data)
A simple and handy solution is :
function myFunc(success) {
//do what you want HERE.
console.log(success)
}
fetch('https://reqres.in/api/users?page=2')
.then(data => data.json())
.then(success => myFunc(success));
Easiest approach is to use async/await method.
Simply copy & paste the following code in your chrome dev console to see the magic:
async function githubUsers() {
let response = await fetch('https://api.github.com/users')
let users = await response.json()
console.log(users)
}
githubUsers()

Categories