how to save promise chaining event in javaScript - javascript

I'm making a promise chained fetch call to an API and using it to get the desired data from it. I can't figure out how to save the resulting array which I am logging to the console and then export it to use it another javaScript file.
fetch('http://api.waqi.info/feed/delhi/?token=66cc9b64ec97aff8a78266ca41b082edf3e9a65a')
.then(res => res.json())
.then(response_body => Object.values(response_body.data.iaqi).map(({v}) => v))
.then(console.log)

You can just export your fetch call in a function and return your Promise.
Here is a minimal example:
// == api.js ==
export const getData = () => {
return fetch('http://api.waqi.info/feed/delhi/?token=66cc9b64ec97aff8a78266ca41b082edf3e9a65a')
.then(res => res.json())
.then(response_body => Object.values(response_body.data.iaqi).map(({v}) => v))
.then(console.log)
}
// == otherfile.js ==
import { getData } from './api.js'
const myFunction = () => {
getData().then(res => {
// do your stuff
})
}
// Async/await style
const myFunction = async () => {
const res = await getData()
}

Related

Struggling with promises and async functions in React

I'm working on a React project where I have a function that fetches paginated data recursively. This function is defined in another function, where I activate the loading screen with showLoading() at the start, where I'm calling the fetching data function in the body and deactivate the loading screen with hideLoading() at the end. The function:
const fetchPlaylist = (playlistId) => {
showLoading()
const getPlaylistDataRecursively = (url) => {
fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
.then(response => response.json())
.then(data => {
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
getPlaylistDataRecursively(next_url)
}
})
}
getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
hideLoading()
}
I believe I can attach a promise to the getPlaylistDataRecursively call with the then keyword but I'm getting a TypeError: Cannot read property 'then' of undefined. Probably because getPlaylistDataRecursively doesn't return anything. How do I make sure that hideLoading is called after getPlaylistDataRecursively is done?
You always need to return a promise.
const fetchPlaylist = (playlistId) => {
showLoading()
const getPlaylistDataRecursively = (url) => {
return fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
.then(response => response.json())
.then(data => {
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
return getPlaylistDataRecursively(next_url)
}
})
}
return getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
.then(() => hideLoading());
}
Or, using async/await:
const fetchPlaylist = async (playlistId) => {
showLoading()
const getPlaylistDataRecursively = async (url) => {
const response = await fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
const data = response.json()
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
await getPlaylistDataRecursively(next_url)
}
}
await getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
hideLoading()
}

React: async and await not working with fetch

I have API on Node server returning JSON like this when called:
{"result":[{"ProductID":1,"ProductName":"iPhone10","ProductDescription":"Latest smartphone from Apple","ProductQuantity":100}]}
I'm trying to display all of that information to user using fetch API with React but no matter what my call returns undefined. Here is my React code:
const [products, setProducts] = useState({})
async function getProducts() {
await fetch(`http://127.0.0.1:5000/listProducts`)
.then(response => response.json())
.then(response=>{
setProducts({products:response.result})
console.log(response.result);
products.map(products =>
<h1>{products.ProductName}</h1>
<h1>{products.ProductDescription}</h1>
)
})
.catch(err=>console.error(err))
}
Function getProducts() is called once when page is loaded. What I'm doing wrong? Thanks in advance.
Try this it will work
const handleFetchData = async () => {
const response = await fetch(`https://api.unsplash.com/photos/random?client_id=${process.env.NEXT_PUBLIC_UNSPLASH_API_ACCESS_KEY}`);
const data = await response.json();
console.log(data);
}
useEffect(() => {
handleFetchData();
},[])
Your function is doing it wrong :
The name should be getAndSetProducts or even setProducts / initProducts because it returns a Promise<void> since you don't actually return anything ;
You're setting inside products an object { products: Product[] }, I think you want only Product[] (an array of Products) else you'll have to get products by doing products.products ;
The map is useless, since you don't do anything with the map response, plus the variable products in the map overwrite the one imported (may cause some errors later).
Try to do :
const [products, setProducts] = useState([]); // Array instead of object
async function initProducts() {
await fetch(`http://127.0.0.1:5000/listProducts`)
.then(response => response.json())
.then(response => {
setProducts(response.result);
console.log(response.result);
)
.catch(err => console.error(err));
}
function getProductsHtml() {
return products.map(product =>
<h1>{product.ProductName}</h1>
<h1>{product.ProductDescription}</h1>
);
}
You can call initProducts when component initialize and return getProductsHtml inside your jsx render.
Try this...
const [products, setProducts] = useState({})
React.useEffect(() => {
const fetchData = async () => {
const result = await fetch('http://127.0.0.1:5000/listProducts')
// console log here to determine how to set products
console.log(result)
setProducts(result)
}
fetchData()
}, [])
React.useEffect(() => {
if (!!products) {
// here you could access products!
}
}, [products])
if (!products) return null
return products.map((product) => (
<>
<h1>{products.ProductName}</h1>
<h1>{products.ProductDescription}</h1>
</>
))
If you are using Async, then you can use response.status as shown below
const response = await fetch("URL", {
body:BODY_DATA,
method:'POST',
headers: { "Content-Type": "application/json"
});
if(response.status === 200){
// Complete your action
} else {
// Show error
}
you can't use async await with .then() you should only use async await or .then() only

Uncaught TypeError: Cannot read property 'then' of undefined at HTMLFormElement.<anonymous>

All code work good, but when I put then to the returned module all code crashes and throws error. Is the problem from that the export is function? If it is not from the function may someone explain why?
This is the module
export default {
search: function(searchTerm, searchLimit, sortBy) {
fetch(
`http://www.reddit.com/search.json?q=${searchTerm}&sort=${sortBy}&limit=${searchLimit}`
)
.then(res => res.json())
.then(data => data.data.children.map(data => data.data))
.catch(err => console.log(err));
}
};
This is actual main JavaScript file
import reddit from "./redditApi";
const searchForm = document.querySelector("#search-form");
const searchInput = document.querySelector("#search-input");
// form eventlistener
searchForm.addEventListener("submit", e => {
e.preventDefault();
// get search term
const searchTerm = searchInput.value;
// get sort
const sortBy = document.querySelector('input[name="sortby"]:checked').value;
// get limit
const searchLimit = document.querySelector("#limit").value;
// check input
if (searchTerm === "") {
// show message
showMessage("Please add a search Term!", "alert-danger");
}
// clear input
searchInput.value = "";
// search reddit
reddit.search(searchTerm, searchLimit, sortBy).then(results => {
console.log(results);
});
});
fetch returns a promise, but search doesn't have any return statement at all.
After you call catch on it, the promise is discarded.
If you want to use it outside the search function then you need to return it.
If you intend to do that
reddit.search(searchTerm, searchLimit, sortBy)
.then(results => {
console.log(results);
})
.catch(error => {
console.log(error);
});
you should wrap fetch inside a Promise.
example:
export default {
search: (searchTerm, searchLimit, sortBy) => {
return new Promise((resolve, reject) => {
fetch(`http://www.reddit.com/search.json?q=${searchTerm}&sort=${sortBy}&limit=${searchLimit}`)
.then(res => res.json())
.then(data => resolve(data.data.children.map(data => data.data)))
.catch(err => reject(err));
});
}
};

Javascript fetch api

i'm trying to assign the variable countries to the response of the fetch api but when i print out countries i get undefined ? can anyone explain to me why ? and a solution if it is possible.
async function getCountries(url) {
const data = await fetch(url);
const response = await data.json();
return response;
}
let countries;
document.addEventListener('DOMContentLoaded', () => {
getCountries('https://restcountries.eu/rest/v2/all')
.then(res => countries = res)
.catch(err => console.log(err));
})
console.log(countries);
function getCountries(url) {
return new Promise((resolve,reject)=>{
fetch(url).then(res => {
//You can parse the countries from the api response here and return to the
//event listener function from here using the resolve methood call parameter
resolve(res);
})
.catch(err => console.log(err));
})
}
document.addEventListener('DOMContentLoaded', () => {
getCountries('https://restcountries.eu/rest/v2/all')
.then(res => {
//the returned value after api call and parsing will be available here in res
})
})
Or if you dont want another function for this one you can directly get it using the following way,
document.addEventListener('DOMContentLoaded', () => {
let countries;
fetch('https://restcountries.eu/rest/v2/all')
.then(res => {
//the returned value after api call and parsing out the countries hereit self
countries = res.data.countries;
})
})

is it normal to pass callback into a async function and even wrap it again?

app.js
import test from "./asyncTest";
test().then((result)=>{
//handle my result
});
asyncTest.js
const test = async cb => {
let data = await otherPromise();
let debounce = _.debounce(() => {
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then( => response.json())
.then(json => json );
}, 2000);
};
export default test;
The fetch result "json" I intend to return is unable to be the return value of "test" function since the value only available in an inner function scope such as debounce wrapper. Since above reason, I tried to pass a callback function and wrap the callback to be Promise function(pTest) as below.
const test = async cb => {
let debounce = _.debounce(() => {
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(response => response.json())
.then(json => cb(null, json))
.catch(err => cb(err));
}, 2000);
};
const pTest = cb => {
return new Promise((resolve, reject) => {
test((err, data) => {
if (err) reject(err);
resolve(data);
});
});
};
export default pTest;
This way works for me, but I'm wondering if it's correct or are there any ways to solve this scenario?
The fetch API already returns a promise. Wrapping it in another Promise object is actually an anti-pattern. it is as simple as the code below:
/*export*/ async function test() {
let data = await otherPromise();
return fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(response => response.json())
.then(json => {
return {
json: json,
data: data
}
});
};
function otherPromise() {
return new Promise((resolve, reject) => {
resolve('test for data value');
});
}
// In index.js call
test().then(res => {
console.log(res)
});

Categories

Resources