Search code examples
reactjsfetchflickr

Nested fetch/then methods


I am using the flickr API to search images and I would like to get photos with theirs tags at same time.

To do it, I need first to use flickr.photos.search method to fetch the photo_id and build the photo url (1st and 2nd 'then' methods). In the 3th 'then' part I used another API method flickr.photos.getInfo to get the tags for each photo and finally return urlPhoto and tagsInfo like json.

The problem is that tagsInfo variable continues been a promise and I can not render the tags (array) of the photo. However, urlPhoto has a correct value.

export function fetchAll(...) {
    return fetch(BASE_URL + encodeGetParams(params1), options)
    .then(response => {
      return response.json();
    })
    .then((data) => {
      return data.photos.photo.map(e => 
        ({
          "photo_id": e.id,
          "urlPhoto": 'https://farm'+e.farm+'.staticflickr.com/'+e.server+'/'+e.id+'_'+e.secret+'.jpg',
        })
      )
    })
    .then((data) => {
      return data.map(e => {
        const url = BASE_URL + encodeGetParams({ ...params2, "photo_id": e.photo_id });
        const tagsInfo = fetch(url, options)
        .then(data => data.json())
        .then(data => data.photo.tags.tag.map(e => e._content));

        return {
          "urlPhoto": e.urlPhoto,
          "tagsInfo": tagsInfo       
        }
      }
      )
    })
}

Solution

  • You could create a separate promise for each element in the array, use Promise.all on those promises and return that.

    export function fetchAll(/* ... */) {
      return fetch(BASE_URL + encodeGetParams(params1), options)
        .then(res => res.json())
        .then(data => {
          const promises = data.photos.photo.map(e => {
            const result = {
              urlPhoto: `https://farm${e.farm}.staticflickr.com/${e.server}/${e.id}_${e.secret}.jpg`
            };
            const url = BASE_URL + encodeGetParams({ ...params2, photo_id: e.photo_id });
    
            return fetch(url, options)
              .then(res => res.json())
              .then(data => {
                result.tagsInfo = data.photo.tags.tag.map(e => e._content);
    
                return result;
              });
          });
    
          return Promise.all(promises);
        });
    }