Как я должен обработать отсутствующее изображение в моем плагине?

#jquery #jquery-plugins #error-handling

#jquery #jquery-плагины #обработка ошибок

Вопрос:

Я написал плагин jQuery под названием waitForImages. По сути, это дает возможность запускать обратные вызовы при загрузке изображений.

Недавно я получил запрос функции, чтобы каким-то образом заставить код уведомлять об ошибке при загрузке изображения.

Может ли плагин вызывать функцию, когда изображение не найдено?

Я подумал о добавлении дополнительного аргумента, который можно было бы проверить, было ли изображение загружено успешно или нет.

 image.onerror = function() {
     eachCallback.call(img.element, allImgsLoaded, allImgsLength, true);
}
  

Затем пользователь мог проверить последний аргумент, чтобы увидеть, соответствует ли он true , и если да, произошла ошибка при загрузке изображения.

Хотя эта идея мне не нравится. Что, если я захочу добавить дополнительный аргумент позже? Следует ли вызывать один и тот же обратный вызов для успешной и неудачной загрузки изображения?

Затем я подумал о том, чтобы создать исключение, если изображение не найдено.

 throw new Error(img.src '   does not exist');
  

Это, однако, не так гибко для перехвата, вам нужно будет вызвать плагин следующим образом…

 try {
   $('body').waitForImages();
} catch (exception) {
    // Which image didn't load?
    alert(exception.message);
}
  

Каков был бы наилучший способ обработки, если изображение не загрузилось в мой плагин?

Ответ №1:

Я бы добавил конкретный обратный вызов для условий ошибки.

У вас уже есть это:

 $('selector').waitForImages({
    finished: function() {
        ...
    },
    each: function() {
       ...
    },
    waitForAll: true
});
  

Вам следует подумать о том, чтобы изменить его на:

 $('selector').waitForImages({
    finished: function() {
        ...
    },
    finishedError: function() {
        ...
    },
    each: function() {
       ...
    },
    eachError: function() {
       ...
    },
    waitForAll: true
});
  

Вы также могли бы использовать «finishedSuccess», если задано, просто чтобы сохранить его согласованным.

Я предпочитаю это по нескольким причинам:

  1. Это отделяет обработку ошибок
  2. У вас может быть другой набор аргументов для успешных или неудачных обратных вызовов
  3. Вы легко добавляете обратные вызовы для различных ошибок (маловероятно в данном случае)

Пожалуйста, не создавайте исключений. Неперехваченное исключение приведет к прерыванию выполнения JavaScript. Вероятно, это не то, что вы захотите сделать только потому, что изображение не загрузилось.

Ответ №2:

Попробуйте это: (DOM Element .complete var)

 $('img').each(function(){
     if($(this).complete != 'true'){
          /* workarround here */
     }
})
  

СОВЕТ: Если вы обнаружили некоторые изображения, которые не загружаются, вы могли бы заменить URL-адреса изображением по умолчанию, сообщающим, что «изображение не найдено» 🙂

Комментарии:

1. Спасибо за ваш ответ, но я не уверен, насколько это актуально.

2. «Какой был бы наилучший способ справиться, если изображение не загрузилось в мой плагин?» я попытался ответить на ваш вопрос, это, кажется, лучший способ. Использование .complete var внутри вашего плагина waitForImages Надеюсь, я смогу помочь. Извините за мой плохой английский.

Ответ №3:

Хороший плагин 🙂

После того, как я изучу ваш код, я бы поместил ошибку после этого фрагмента кода:

 image.onload = function() {
    allImgsLoaded  ;
    eachCallback.call(img.element, allImgsLoaded, allImgsLength);
    if (allImgsLoaded == allImgsLength) {
        finishedCallback.call(obj[0]);
        return false;
    };
};

image.onerror = function() {
    errorCallback.call(img.element);
    return false;
}
  

Конечно, вам нужно ввести новую функцию обратного вызова, такую как

 $('selector').waitForImages(function() {

    alert('All images are loaded.');

}, function(loaded, count) {

   alert(loaded   ' of '   count   ' images have loaded.');
   $(this).addClass('loaded');

}, function(img) {
   alert('error');
});
  

Надеюсь, это поможет
🙂

Ответ №4:

Похоже, для этого вы хотели бы использовать отложенные объекты jQuery:http://api.jquery.com/category/deferred-object / .

По сути, это позволяет вам создать объект ( var x = jQuery.Deferred() ). Затем вы можете добавить обработчики завершения, успеха и ошибок, как вы бы добавили к jQuery.ajax объекту, используя x.always(callback) , x.done(successCallback) x.fail(errorCallback) соответственно. Очевидно, что названия функций и / или свойств для прикрепления таких обработчиков к вашему внутреннему отложенному объекту зависят от вас.

Вы могли бы передать текстовый статус этим обработчикам, таким как jQuery.ajax, или даже количество завершенных / исправленных изображений, когда вы разрешаете отложенный объект с помощью x.resolveWith и x.rejectWith .

Я бы подумал, что такие функции лучше всего подходят для общего завершения / успеха / неудачи загрузки изображений, но вы также могли бы использовать одну и ту же систему для каждого изображения в отдельности. При вызове вашего плагина вы должны сохранять обработчики в локальном объекте и создавать новый отложенный объект для каждого изображения, с которым вы сталкиваетесь, добавляя обратные вызовы к этому новому отложенному объекту.

Ответ №5:

В любом случае это указывает на то, что вам, вероятно, следует привязать свою функцию в строке 103 к обоим error и load , и, вероятно, следует принять событие в качестве аргумента для этой функции. В противном случае вы никогда не поднимете флаг о том, что браузер завершил обработку изображения. Это может быть так же просто, как вызов $(image).bind("load error", function(e) { allImagesLoaded ; ... }) . Внутри функции вы можете перейти к параметрам обработки ошибок, проверив e.type === "error" , например, подняв флаг, что произошел сбой, и обратный вызов с ошибкой должен быть выполнен после завершения всех изображений.

У вас уже есть обработка для объекта options. Лучшее, что можно было бы сделать, это разрешить пользователю выполнять обратные вызовы при возникновении ошибок, добавив дополнительные параметры в этот объект. Это соответствовало бы подходу других распространенных плагинов и базовых функций jQuery. Я бы предложил рассмотреть модель обратного вызова для jQuery.ajax() . Разрешить пользователям указывать обратные вызовы, для success которых выполняются при успешной загрузке всех изображений, error которые допускают другой путь выполнения при возникновении любого события ошибки и complete которые выполняются после того, как все изображения запустили свои события, независимо от успеха или неудачи. Вы также можете захотеть добавить опцию обратного вызова для обработки ошибок сразу после сбоя одного изображения, хотя я не обязательно чувствую, что это соответствует области плагина. Не раздувайте его, если это действительно не добавляет ценности функциональности.