2

I am working on an application that returns a list of ids from first fetch request. After getting the ids, I have to loop through the ids and get details of each item and then display it on the screen.

  fetch(TOP_STORIES)
  .then(function(response){
    return response.json()
  }).then(function(storyIds){
      // storyIds is [22,33,44,55,66,77,88,99,123,213,342,45456,778,888]
      // is this the best way to fetch all the details of the story
      storyIds.forEach(function(storyId){

        let storyDetailsURL = `https://someurl/v0/item/${storyId}.json?print=pretty`

        fetch(storyDetailsURL)
        .then((response) => response.json())
        .then((story) => {
            displayStory(story)
        })
      })

  })

My question is that is looping the best way to get the results?

UPDATE: Promise.all is giving me issues:

enter image description here

UPDATE: Using Async and Await

async function fetchTopHeadlinesAsyncAwait() {

  let response = await fetch(TOP_STORIES)
  let storyIds = await response.json()

  for(let storyId of storyIds) {
    console.log(storyId)
    let storyDetailsURL = `someurl/er/tg/${storyId}.json?print=pretty`
    let response = await fetch(storyDetailsURL)
    let story = await response.json()
    displayStory(story)
  }
}
john doe
  • 9,220
  • 23
  • 91
  • 167
  • i don't like it because it hammers the server with all requests at once. It would usually be better to request them one at a time. To do that, I define and index and make a function called next() that fetches a single item by id. next() checks the index to see if it's the last one. If not, increment the index and call next(), otherwise stop and do something else. Don't forget to call next() manually once at the bottom of the containing context... – dandavis Mar 14 '19 at 18:09
  • by the way, if you switch to using *async* / *await* style code instead of *Promise.then*, it would *clean up* nicely and be more convenient to use. *Promises* are great though. Other than than getting the story detail only when needed is what I would do. – gkelly Mar 14 '19 at 18:11
  • Can you try just remove the json() function line ? – Bjarne Gerhardt-Pedersen Mar 14 '19 at 19:04
  • @BjarneGerhardt-Pedersen If I remove json() then how will I get json from the response? – john doe Mar 14 '19 at 19:17
  • 1
    ahh, async/await. so much cleaner. – gkelly Mar 14 '19 at 19:24
  • 1
    @johndoe i updated my answer so json should now work with the array of promises. The .json() didnt work, because it was called on the array of responses. – Bjarne Gerhardt-Pedersen Mar 15 '19 at 06:53

1 Answers1

4

You can use Promise.all functionality to fetch a list of async actions. They will be completed when all are successful.

Here is example of your code with Promise all, let me know how it works :)

const fetchStories = () => {
  let response = await fetch(TOP_STORIES);
  let storyIds = await response.json();

    let urls = [];
    storyIds.forEach(function(storyId) {
      urls.push(`https://someurl/v0/item/${storyId}.json?print=pretty`);
    });

    Promise.all(
      urls.map(url =>
        fetch(url)
          .then(response => response.json())
          .catch(err => console.error(err))
      )
    ).then(stories => stories.forEach(story => displayStory(story)));
}