A bit of an ambiguous title, but I'll explain...
I am making a fetch
call to 4 different URLs from The Movie Database . Once these fetch calls retrieve the data, it will then setState
and update my initial state. However, I don't want my page to load until all of the data is retrieved, so I am using Promise.all
(or attempting to).
My code so far...
state = {
movies: {
trending: {},
topRated: {},
nowPlaying: {},
upcoming: {},
},
};
const allMovieURLs = {
trending: `https://api.themoviedb.org/3/trending/all/day?api_key=${API_KEY}`,
topRated: `https://api.themoviedb.org/3/movie/top_rated?api_key=${API_KEY}&language=en-US&page=1`,
nowPlaying: `https://api.themoviedb.org/3/movie/now_playing?api_key=${API_KEY}&language=en-US&page=1`,
upcoming: `https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1`
};
//initialize an empty array to Promise.all on
const promiseArr = [];
//loop through movie URLs, call fetch + json()
for (const movies in allMovieURLs) {
//create an object that directly describes the data you get back from the url with a key
const obj = {
[movies]: fetch(allMovieURLs[movies]).then(res => res.json())
};
//push that object into an array so you can use Promise.all
promiseArr.push(obj);
Now what I have here is an array ( promiseArr
) of objects that have the correct key with the correct Promise
stored inside of them.
My next plan was going to be to call Promise.all
on them, but I need an array of promises. After I get the actual data back from the URL calls, I wanted to store them back in the object, to the correct corresponding key?
I've been stuck at this part for a couple hours now...any tips would be appreciated!
You can use async/await
and Object.entries()
to convert a JavaScript plain object to an array of arrays of key, value pairs
(async() => {
for (const [movie, url] of Object.entries(allMovieURLs)) {
try {
allMovieURLs[movie] = await fetch(url).then(res => res.json())
.catch(e => {throw e})
} catch(e) {
console.error(e)
}
}
})()
Don't call then when adding to promise array. Instead call it in promise all
const trending = fetch(trending);
...
Promise.all([trending, topRated, nowplaying, upcoming]).then(([trending, topRated, nowplaying, upcoming]) => {
movies.trending = trending.json();
....
});
You could just also store the promises themselves in another array.
function fetch() { var time = Math.random() * 1E3; return new Promise(function (res, rej) { setTimeout(function () { res(time); }, time); }); } const API_KEY = ""; const allMovieURLs = { trending: `https://api.themoviedb.org/3/trending/all/day?api_key=${API_KEY}`, topRated: `https://api.themoviedb.org/3/movie/top_rated?api_key=${API_KEY}&language=en-US&page=1`, nowPlaying: `https://api.themoviedb.org/3/movie/now_playing?api_key=${API_KEY}&language=en-US&page=1`, upcoming: `https://api.themoviedb.org/3/movie/upcoming?api_key=${API_KEY}&language=en-US&page=1` }; const promiseArr = []; const promises = []; for (const movies in allMovieURLs) { const obj = { [movies]: undefined }; promises.push(fetch(allMovieURLs[movies]).then(res => obj[movies] = res)); promiseArr.push(obj); } Promise.all(promises).then(function () { console.log(promiseArr); });
If that is not feasible, you can do something like: Promise.all(promiseArr.map(obj => Object.values(obj)[0]))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.