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?
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