user3331344
user3331344

Reputation: 991

Handle async foreach loop then dispatch to redux

I am looking to get search results from the youtube api and I want to loop through the results making a call to get each videos information. Then I want to dispatch result of the pending api calls to the redux store. My problem is that I want to make my code reusable so I am having trouble getting a function to return when the loop is done.

So what I am trying to do is set up 3 different functions. The first one will have the initial api call to get search results. Fairly simple. The second one will loop through the results from the first function and return all of the individual videos information. The third function will be called from the mapDispatchToProps method in redux to dispatch the results to the redux store.

My problem is in the second function I cannot get the results of the foreach loop to return. I have tried to return a new promise and if(videoArr.items.length === videos.length) resolve() but that doesn't work and I tried to just return videos after the if condition but that doesn't work either.

const key = ''

const getVideos = (url) => {
  return fetch(url + key)
  .then(res => res.json())
}

// ---- Problem is returning videos from this function below finish the setVideos function
const getInfo = (videoArr) => { 
  let videos = [];
  videoArr.items.forEach(function(video, index){
    let videoId = video.id.videoId ? video.id.videoId : video.id
    fetch('https://www.googleapis.com/youtube/v3/videos?part=snippet%2CcontentDetails%2Cstatistics&id=' + videoId + '&key=' + key)
    .then(res => res.json())
    .then((result) => {
      videos = [...videos, result.items[0]]
      if(videoArr.items.length === videos.length) return videos
    })
  });
}

const setVideos = (url) => dispatch => {
  getVideos(url)
  .then(result => getInfo(result))
  .then(videos => {
    dispatch({
      type: SET_VIDEOS,
      payload: videos
    })
  })
}

I'm not really sure if this is the best approach or not but I will have a few of the functions like setVideos() calling different urls to getVideos() for paging and things like that. I can get everything working if I just write one long function and dispatch from in the then() inside the for loop once the if condition is met but then I will have a bunch of code and is seems a bit much so I would like to consolidate it into something like what I am trying to achieve above. Hope that makes sense any help would be appreciated.

Upvotes: 4

Views: 2586

Answers (1)

errnesto
errnesto

Reputation: 832

I thik Promise.all will solve your problem:

let promises = videoURLs.map(videoURL => {
  return fetch(videoURL)
    .then(res => res.json())
})
Promise.all(promises).then(array => {
  …
})

Upvotes: 4

Related Questions