Search code examples
javascriptjqueryflickr

src attribute is undefined after fetching and displaying data after an ajax get request is made to flickr.photos.search API


I find this problem particulary interesting because I am recieving the data back from the server, which is being passing into an array. I know that I am getting back the data after logging to the console the photoGallery array. However, in the displayImage() function, after the html has been added, the src attributes inside the figure are undefined. Any clues?

Undefined Image
PhotoGalleryArray

Here is some example code:

let photoGallery = [];
let searchRequests;
let searchReceived;

$(document).ready(function () {
    let searchArray = ["dog", "cat", "horse", "tree", "bug"];
    searchFlickr(searchArray);
});

After the document loads, the searchFlickr function is called

function searchFlickr(searchArray) {
    photoGallery = [];
    searchRequests = searchArray.length;
    searchReceived = 0;
    let flickr_searchStr = "";
    $('#Gallery figure').fadeOut();
    searchArray.forEach(function (element) {
        flickr_searchStr = "https://api.flickr.com/services/rest/?method=flickr.photos.search&sort=relevance&content_type=7&format=json&nojsoncallback=1&per_page=1&text=" + element + API_KEY
        $.get(flickr_searchStr, function (data) {
            fetchImage(data);
        })
    })
}

For each jSON object we get back, the fetchImage function is called

function fetchImage(data) {
    searchReceived++
    for (let i = 0; i < data.photos.photo.length; i++) {
        let imageObject = {id: data.photos.photo[i].id,title: data.photos.photo[i].title}
        photoGallery.push(imageObject);
        getSizes(imageObject);
    }
}

function getSizes(imageObject) {
    let getSizesStr = "https://api.flickr.com/services/rest/?method=flickr.photos.getSizes&format=json&nojsoncallback=1" + API_KEY + "&photo_id=" + imageObject.id;
    $.get(getSizesStr, function (data) {

        imageObject.url_small = data.sizes.size[3].source;
        //Check if searchRecieved is equal to the length of photosRequests then call displayImage function
        if (searchReceived == searchRequests) {
            displayImage(photoGallery);
        }
    });
}

This is where I cannot figure out what is going on, if you console.log(photoGallery), you will get back the array of data. But after loop has finished only one image actually has a url in the src attribute, the rest are undefined.

function displayImage(photoGallery) {
    let htmlStr = "";
    for (let i = 0; i < photoGallery.length; i++) {
        htmlStr += `<figure><img src="${photoGallery[i].url_small}"><figcaption>${photoGallery[i].title}</figcaption></figure>`;
    }
    $('#Gallery').html(htmlStr);
    $('#Gallery figure').fadeIn(500);
}

EDIT - The jSON object passed to the fetchImage() function looks like this:

{ "photos": { "page": 1, "pages": "432757", "perpage": 1, "total": "432757", 
"photo": [
  { "id": "42046641202", "owner": "65984184@N05", "secret": "e94c9e7c26", "server": "910", "farm": 1, "title": "Painted Dogs", "ispublic": 1, "isfriend": 0, "isfamily": 0 }
] }, "stat": "ok" }

EDIT - The jSON object called in the getSizes() function looks like this:

{ "sizes": { "canblog": 0, "canprint": 0, "candownload": 0, 
    "size": [
      { "label": "Square", "width": 75, "height": 75, "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38_s.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/sq\/", "media": "photo" },
      { "label": "Large Square", "width": "150", "height": "150", "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38_q.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/q\/", "media": "photo" },
      { "label": "Thumbnail", "width": 100, "height": 67, "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38_t.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/t\/", "media": "photo" },
      { "label": "Small", "width": "240", "height": "160", "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38_m.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/s\/", "media": "photo" },
      { "label": "Small 320", "width": "320", "height": "213", "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38_n.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/n\/", "media": "photo" },
      { "label": "Medium", "width": "500", "height": "333", "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/m\/", "media": "photo" },
      { "label": "Medium 640", "width": "640", "height": "426", "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38_z.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/z\/", "media": "photo" },
      { "label": "Large", "width": "1024", "height": "682", "source": "https:\/\/farm6.staticflickr.com\/5254\/5412377706_d77700fc38_b.jpg", "url": "https:\/\/www.flickr.com\/photos\/parismadrid\/5412377706\/sizes\/l\/", "media": "photo" }
    ] }, "stat": "ok" }

Solution

  • Ok, this is a weird one but looks like if you define the property url_small when you are creating the object imageObject, will remove the exception, I just tested it locally and I thought initially that may be using Object.definProperty() to add a new property to the object imageObject might fix this issue along with using for..in loop with Object.hasOwnProperty() check but nothing seemed to work unless I define the property at the time of declaring the object and then adding the value to it inside getSizes().

    Change your object in the fetchImage() to the following

    let imageObject = {
        id: data.photos.photo[i].id,
        title: data.photos.photo[i].title,
        url_small: ''
    }