Question

I have a function that pulls images from an API to insert them in an animated scroller. It looks like this (simplified for clarity):

function getPhotos(id) {
    $.when(Service.getPhotos(id))
        .then(function(results) {
            var photos = results.photos,
                scroller = $("#scroller");

            // Add the photos to the scroller
            for (var i = 0; i < photos.length; i++) {
                var photo = photos[i].url;

                // Only add a photo if its URL is valid
                if (photoExists(photo) == 200) {
                    scroller.append("<li><img src='" + photo + "' /></li>");    
                } else {
                    console.log("Photo " + photo + " doesn't exist");
                }
            }
        })
        .fail(function(err) {
            console.log(err);
        });
}

However, the photo URLs don't always resolve to valid images, so I run them through the photoExists() function:

function photoExists(photo) {
    var http = jQuery.ajax({
        type: "HEAD",
        url: photo,
        async: false
    });

    return http.status;
}

If a given photo URL returns a status code of 200, then I know the image exists and I insert it into the scroller; otherwise, I skip over it so that I don't insert a broken image.

The problem here is that async: false – because this isn't asynchronous, the whole UI locks up until everything completes, which can be a very long time depending on how many photo URLs I have to loop through.

If I use async: true, however, then the photoExists() function attempts to return the status code before the AJAX request itself actually completes – so photoExists(photo) never returns 200, resulting in nothing being added to the scroller.

How would I adjust this so that photoExists() can run asynchronously and therefore avoid locking up the UI, but still return the correct status code so I can insert the photos into the scroller properly?

Was it helpful?

Solution

You need to provide a callback function for your photoExists function. Something like this:

function photoExists(photo, callback) {
    var http = jQuery.ajax({
        type: "HEAD",
        url: photo,
        async: true,
        success: function(){
            callback(photo, true);
        },
        error: function(){
            callback(photo, false);
        }
    });
}

Then use it like so:

for (var i = 0; i < photos.length; i++) {
    var photo = photos[i].url;

    // Only add a photo if its URL is valid
    photoExists(photo, function(photo, isSuccessful){
        if (isSuccessful) {
            scroller.append("<li><img src='" + photo + "' /></li>");    
        } else {
            console.log("Photo " + photo + " doesn't exist");
        }
    });
}

Added photo to callback function to avoid possible closure issues with the for loop

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top