Как мне переписать эту функцию, чтобы она была асинхронной?
У меня есть функция, которая извлекает изображения из API, чтобы вставить их в анимированный скроллер. Это выглядит так (упрощено для ясности):
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);
});
}
Однако URL-адреса фотографий не всегда соответствуют действительным изображениям, поэтому я запускаю их через photoExists()
функция:
function photoExists(photo) {
var http = jQuery.ajax({
type: "HEAD",
url: photo,
async: false
});
return http.status;
}
Если заданный URL-адрес фотографии возвращает код состояния 200
тогда я знаю, что изображение существует, и вставляю его в скроллер; в противном случае я пропускаю его, чтобы не вставить поврежденное изображение.
Проблема здесь в том, что async: false
- потому что это не асинхронно, весь пользовательский интерфейс блокируется до тех пор, пока все не завершится, что может занять очень много времени в зависимости от того, сколько URL-адресов фотографий я должен просмотреть.
Если я использую async: true
Однако тогда photoExists()
функция пытается вернуть код состояния до того, как сам запрос AJAX фактически завершится - так photoExists(photo)
никогда не вернется 200
, в результате чего ничего не будет добавлено в скроллер.
Как бы я настроить это так, чтобы photoExists()
может работать асинхронно и, следовательно, избегать блокировки пользовательского интерфейса, но при этом возвращать правильный код состояния, чтобы я мог правильно вставить фотографии в скроллер?
1 ответ
Вы должны предоставить функцию обратного вызова для вашего photoExists
функция. Что-то вроде этого:
function photoExists(photo, callback) {
var http = jQuery.ajax({
type: "HEAD",
url: photo,
async: true,
success: function(){
callback(photo, true);
},
error: function(){
callback(photo, false);
}
});
}
Тогда используйте это так:
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");
}
});
}
Добавлена фотография в функцию обратного вызова, чтобы избежать возможных проблем с закрытием цикла for