Динамически сгенерированное изображение запрашивается дважды при использовании отложенной загрузки jquery в Google Chrome

У меня есть обработчик файлов ashx, который генерирует мои изображения.

<img src="www.mywebsite.com/action/getimage.ashx?imageID=f8be4bf6&width=100&height=700&bgcolor=999" />

Это все работает нормально.

Теперь я хочу использовать ленивую загрузку. Используя этот плагин отложенной загрузки jquery

Итак, я настроил свои html-изображения следующим образом:

<img src="imageplaceholder.gif" original-data="www.mywebsite.com/action/getimage.ashx?imageID=f8be4bf6&width=100&height=700&bgcolor=999" />

И добавил следующий скрипт:

$(function() {
   $("img").lazyload();
});

Я заметил, что на вкладке сети инструментов Google Chrome Devoloper есть два вызова этого обработчика файлов.

Я создал тестовую скрипту здесь: ссылка. Если вы прокрутите эту скрипту вниз, вы увидите два запроса изображения, когда изображение загружается в Google Chrome. В Firefox и IE это работает только с одним вызовом.

Есть ли способ избежать такого поведения?

ОБНОВИТЬ:

В обработчике файлов устанавливаются следующие заголовки:

[0] "Server"    "Microsoft-IIS/7.5"
[1] "Set-Cookie"    "lang=nl; expires=Tue, 04-Feb-2014 13:08:56 GMT; path=/"

И свойство Expires объекта Response:

context.Response.Expires = 0

person ThdK    schedule 24.01.2013    source источник
comment
Можете ли вы также опубликовать содержимое ProcessRequest обработчика изображений? Причина этого в том, что поведение происходит только в том случае, если data-original использует обработчик изображения (www.mywebsite.com/action/getimage.ashx?imageID=f8be4bf6&width=100&height=700&bgcolor=999), но когда это статическое изображение, такое как http://www.appelsiini.net/attachments/jquery.png, тогда есть только один вызов.   -  person Andy Refuerzo    schedule 30.01.2013
comment
Я тоже это заметил. Статические изображения работают нормально. Обработчик файлов, используемый в скрипте примера, не является обработчиком файлов, используемым в моем собственном решении. Я попробовал разные обработчики файлов, которые нашел в Интернете, чтобы убедиться, что проблема не в моем коде. До сих пор у всех была одна и та же проблема. Поэтому я не думаю, что проблема будет с самим обработчиком изображений.   -  person ThdK    schedule 31.01.2013


Ответы (3)


Я считаю, что основная проблема заключается в том, что Chrome не кэширует изображение. В этой демонстрации Chrome будет выдавать новый запрос каждый раз, когда вы нажимаете кнопку.

Сценарий ленивой загрузки запускает 2 запроса, потому что он сначала (предварительно) загружает изображение в закрытый элемент img, а затем назначает URL-адрес изображения исходному элементу img.

Я предлагаю добавить заголовок Expires или Cache-Control и заголовок Last-Modified или ETag к ответу вашего обработчика изображений, чтобы Chrome кэшировал изображение. (Подробнее о кэшировании см. в Учебнике по кэшированию для веб-авторов и веб-мастеров.)


Обновление: я предлагаю добавить что-то подобное в ваш обработчик изображений (из MSDN):

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
person Jeffery To    schedule 04.02.2013
comment
Если он (предварительно) загружает изображение, разве это не противоречит цели (ленивой) загрузки? - person Andy Refuerzo; 04.02.2013
comment
«Предварительная» загрузка происходит только тогда, когда изображение действительно видно. Я не знаю, как на самом деле работают плагины отложенной загрузки, но я могу сказать, что и первый вызов, и второй вызов выполняются, когда изображение попадает в область просмотра. Я обновил свой вопрос текущими заголовками кэширования ответа в моем обработчике изображений. - person ThdK; 04.02.2013
comment
@ThdK На самом деле ваш комментарий подчеркивает мой ответ о том, что Chrome обрабатывает $("img").attr("src", "") по-другому. Если вы посмотрите в код плагина, line 110 и line 115 — это единственные места, где значение атрибута src установлено в URL-адрес обработчика изображения. В моих тестах при выполнении этих строк запускается запрос на изображение. Единственная разница в том, что перед line 110 скрывается <img />. - person Andy Refuerzo; 04.02.2013
comment
Пожалуйста, посмотрите мое обновление - context.Response.Expires = 0 означает, что изображение может быть кэшировано на 0 минут. - person Jeffery To; 04.02.2013

Когда происходит что-то подобное, убедитесь, что у вас не открыты Chrome DevTools и не установлен флажок «Отключить кеш». Если какой-либо аддон, настройка или что-либо еще приводит к отключению кеша, может произойти то же самое.

person Mark    schedule 31.10.2018
comment
Это на самом деле то, что вызывает эту проблему для меня. Спасибо, что заставили меня проверить это! Сняв флажок «Отключить кеш» в инструментах разработки, все работает нормально, и это не связано с плагином — произойдет с любой ленивой загрузкой библиотеки (в моем случае внутри React) - person easwee; 09.05.2019

Похоже, Google Chrome обрабатывает $("img").attr("src", "") иначе, чем другие браузеры.

Посмотрите исходный код плагина на GitHub и добавьте точка останова в Chrome (пошагово), вызовы обработчика изображения происходят, когда он изменяет атрибут src изображения на значение original-data.

Хотя возможно, что проблема заключается в обработчике изображений (как я уже отмечал ранее), решение, которое я нашел, состояло в том, чтобы изменить line 115 источника плагина из

.attr("src", $self.data(settings.data_attribute));

to

.attr("src", "data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==");

новое значение представляет собой строку в кодировке base64 для прозрачного изображения GIF размером 1 на 1 пиксель.

В своем тесте fiddle найдите в уменьшенной версии второе вхождение

c.data(h.data_attribute)

и измените его на

"data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="

Он по-прежнему будет вызывать дважды, но первый вызов будет незначительным (0kb?), и это изменение не повлияет на другие браузеры.

person Andy Refuerzo    schedule 31.01.2013
comment
Почему этот ответ был отклонен? Я внес ваше изменение в плагин, и затем я вижу, что второй вызов действительно сделан только для 1x1px. Я обсужу этот вариант с кем-нибудь еще здесь, чтобы посмотреть, сможем ли мы это сделать. Я не эксперт по jquery, поэтому я не могу понять, почему эта строка кода действительно работает, и безопасно ли ее изменить на 100%. Так что если у кого-то из вас есть другое мнение на этот счет. Пожалуйста, дай мне знать! Большое спасибо уже за потраченное время на это! - person ThdK; 01.02.2013
comment
Я также озадачен тем, почему Chrome ведет себя так для этого плагина, но я думал, что мы не можем изменить поведение браузера и мы не можем изменить обработчик изображения, поэтому мы остаемся только с плагином. Я также не эксперт по jQuery, поэтому, если вы получите окончательный ответ на это поведение, пожалуйста, опубликуйте его и здесь. :) - person Andy Refuerzo; 01.02.2013
comment
Что касается минуса, я понятия не имею, почему. Я думаю, что это лучшее решение, позволяющее избежать повторного запроса одного и того же изображения в Chrome, если только вы не хотите изменить свой плагин отложенного загрузчика (не спрашивайте меня, какая замена - я не использую). - person Andy Refuerzo; 01.02.2013
comment
@ThdK Вероятно, за это проголосовали, потому что предложенное исправление требует редактирования плагина, это грязное исправление. Например, если плагин загружался из CDN, это было бы невозможно. Просто идея. Я бы проголосовал за этот ответ из-за усилий, которые Энди приложил, чтобы попытаться решить эту проблему для вас, но я не считаю это реальным решением. продолжение - person Ben Carey; 04.02.2013
comment
@ThdK Я считаю, что проблема на самом деле заключается в скрипте, который извлекает изображение. Это показано в моем ответе. Однако я понимаю, что может возникнуть проблема с тем, как Chrome обрабатывает атрибут данных, и в результате мой ответ может оказаться неподходящим. - person Ben Carey; 04.02.2013
comment
Я проголосовал за ответы, потому что ценю ваше время. Мой скрипт вызывается дважды в хроме, мой скрипт запускается только после этого вызова на сервере. Поэтому я думаю, что мы должны посмотреть, почему сделан этот второй запрос. Как бы ни выглядел код в сценарии. Может ли быть проблема с кэшированием заголовков? - person ThdK; 04.02.2013
comment
@BenCarey Я проверил поведение с другими обработчиками изображений (с расширениями .ashx) и получил те же результаты. Я не считаю это грязным исправлением, поскольку плагин является проектом с открытым исходным кодом. :) Вам когда-нибудь приходило в голову, что то, с чем мы сталкиваемся, является ошибкой, характерной только для плагина и хрома при использовании обработчиков изображений asp.net? Другой обработчик изображений, который я тестировал, нашел в Интернете: http://www.recoding.it/Demos/imghandler.ashx?i=~%2fImages%2fphoto_1.jpg&w=220&h=0&pt=Scale&va=Middle&ha=Center&di=&wpath=&wpos=bottom_right&ch=False&cr=0&flip=None&ie=None&rot=Rotate0 - person Andy Refuerzo; 04.02.2013
comment
@AndyRefuerzo В этом случае вы правы в том смысле, что это не связано со сценарием, предоставляющим изображение. В результате я удалю свой ответ. Это вполне может быть ошибка, хотя и очень странная ошибка!! - person Ben Carey; 04.02.2013