Подтвердить что ты не робот

Почему браузеры неэффективно делают здесь 2 запроса?

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

Удивительно, но я обнаружил, что даже когда javascript ожидает загрузки всей страницы, запрос на изображение все еще делает новый запрос! Является ли это известной ошибкой в ​​Firefox и Chrome, или что-то плохое jQuery ajax делает?

Здесь вы можете увидеть проблему, откройте Fiddler или Wireshark и установите ее для записи, прежде чем нажать "запустить":

<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<div id="something" style="background-image:url(http://jsfiddle.net/img/logo-white.png);">Hello</div>
<script>

jQuery(function($) {
    $(window).load(function() {
        $.get('http://jsfiddle.net/img/logo-white.png');
    })
});

</script>

Обратите внимание, что в Firefox он выполняет два запроса, оба приводят к 200-OK, и отправляет все изображение обратно в браузер дважды. В Chromium он, по крайней мере, правильно получает 304 по второму запросу, а не дважды загружает содержимое.

Как ни странно, IE11 загружает весь образ дважды, в то время как IE9 агрессивно кэширует его и загружает его один раз.

В идеале я бы надеялся, что ajax вообще не сделает второй запрос, так как он запрашивает точно такой же URL-адрес. Есть ли причина, по которой css и ajax в этом случае обычно имеют разные кеши, как будто браузер использует различное хранилище кеша для запросов css vs ajax?

4b9b3361

Ответ 1

Помощники в Mozilla рассказали о том, почему это происходит. По-видимому, Firefox предполагает, что анонимный запрос может отличаться от обычного, и по этой причине он делает второй запрос и не считает кешированное значение с разными заголовками одним и тем же запросом.

https://bugzilla.mozilla.org/show_bug.cgi?id=1075297

Ответ 2

Я использую новейший Google Chrome, и он делает один запрос. Но в примере JSFIDDLE вы дважды загружаете jQuery. Сначала с JSFIDDLE и вторым в вашем коде над тегом script. Улучшено: JSFIDDLE

<div id="something" style="background-image:url('http://jsfiddle.net/img/logo-white.png');">Hello</div>

<script>
    jQuery(window).load(function() {
        jQuery.get('http://jsfiddle.net/img/logo-white.png');
    });

    // or

    jQuery(function($) {
        jQuery.get('http://jsfiddle.net/img/logo-white.png');
    });
</script>

jQuery(function($) {...} вызывается, когда DOM готов и jQuery(window).load(...);, если DOM готов и загружается каждое изображение и другие ресурсы. Чтобы обе вложенные вложенные не имеют смысла, см. Также здесь: window.onload vs $(document).ready()

Конечно, изображение загружается два раза на вкладке "Сеть" веб-инспектора. Сначала через ваш CSS и второй через ваш JavaScript. Второй запрос, вероятно, кэшируется.

ОБНОВЛЕНИЕ. Но каждый запрос, если кешированный или нет, показан на этой вкладке. См. Следующий пример: http://jsfiddle.net/95mnf9rm/4/ Есть 5 запросов с кэшированными вызовами AJAX и 5 без кеширования. И 10 запросов отображаются на вкладке "Сеть". Когда вы дважды используете изображение в CSS, он запрашивает только один раз. Но если вы явно делаете вызов AJAX, браузер делает вызов AJAX. Как пожелаете. А потом, возможно, он кэширован или нет, но он явно запросил, не так ли?

Ответ 3

Эта "проблема" может быть <сильным > предполетным тестом CORS.

Я заметил это в своих приложениях некоторое время назад, что вызов для извлечения информации из одностраничного приложения дважды вызывал вызов. Это происходит только при обращении к URL-адресам в другом домене. В моем случае у нас есть API, которые мы создали и используем на другом сервере (другой домен), чем у приложений, которые мы создаем. Я заметил, что когда я использую GET или POST в своем приложении к этим RESTFUL API, вызов получается дважды.

То, что происходит, называется предполетным (https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS), первоначальный запрос делается для сервер, чтобы увидеть, разрешен ли следующий вызов.

Выдержка из MDN:

В отличие от простых запросов "предварительно запрограммированные" запросы сначала отправляют HTTP-запрос методом OPTIONS к ресурсу в другом домене, чтобы определить, безопасно ли отправлять фактический запрос. Запросы межсайтовых запросов предваряются таким образом, поскольку они могут иметь последствия для пользовательских данных. В частности, запрос предваряется, если:

  • Он использует методы, отличные от GET, HEAD или POST. Кроме того, если POST используется для отправки данных запроса с помощью Content-Type, отличного от application/x-www-form-urlencoded, multipart/form-data или text/plain, например. если запрос POST отправляет XML-полезную нагрузку на сервер с помощью приложения /xml или text/xml, тогда запрос предваряется.
  • Он устанавливает пользовательские заголовки в запросе (например, запрос использует заголовок, например X-PINGOTHER)

Ответ 4

Ваша скрипка пытается загрузить ресурс из другого домена через ajax: cross domain request

Думаю, я создал лучший пример. Вот код:

<img src="smiley.png" alt="smiley" />
<div id="respText"></div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
  $(window).load(function(){        
    $.get("smiley.png", function(){
      $("#respText").text("ajax request succeeded");
    });
  });
</script>

Вы можете проверить страницу здесь.

В соответствии с Firebug и сетевой панелью chrome изображение возвращается с кодом состояния 200, а изображение для запроса ajax поступает из кеша:

Firefox: Firebug

Chrome: chrome network panel

Поэтому я не могу найти неожиданного поведения.

Ответ 5

Управление кэшем по запросам Ajax всегда было размытым и ошибочным субъектом (пример). Проблема становится еще хуже с междоменными ссылками.

Ссылка на скрипку, которую вы указали, составляет от jsfiddle.net, который является псевдонимом для fiddle.jshell.net. Каждый код выполняется внутри домена fiddle.jshell.net, но ваш код ссылается на изображение из псевдонима, и браузер будет рассматривать его как междоменный доступ.

Чтобы исправить это, вы можете изменить оба URL на http://fiddle.jshell.net/img/logo-white.png или просто /img/logo-white.png.

Ответ 6

Это может быть выстрел в темноте, но здесь я думаю, что это происходит.

Согласно, http://api.jquery.com/jQuery.get/

dataType
  Type: String
  The type of data expected from the server. 
  Default: Intelligent Guess (xml, json, script, or html).

Дает вам 4 возможных типа возврата. Возвращается тип данных image/gif. Таким образом, браузер не проверяет его кеш для документа src, поскольку он поставляется с другим типом mime.

Ответ 7

Сервер решает, что можно кэшировать и как долго. Тем не менее, это снова зависит от браузера, следует ли следовать ему или нет. Тем не менее большинство веб-браузеров, таких как Chrome, Firefox, Safari, Opera и IE.

То, что я хочу сделать здесь, заключается в том, что ваш веб-сервер может быть настроен так, чтобы он не позволял браузеру кэшировать контент, поэтому, когда вы запрашиваете изображение через CSS и JS, браузер следует вашим заказам сервера и не делает 't кешировать его и, таким образом, он запрашивает изображение дважды...

Ответ 8

Я хочу JS-доступное изображение

Вы пытались использовать CSS с помощью jQuery? Это довольно забавно - у вас есть полный CRUD (создавать, читать, обновлять, удалять) элементы CSS. Например, измените размер изображения на стороне сервера:

$('#container').css('background', 'url(somepage.php?src=image_source.jpg'
    + '&w=' + $("#container").width() 
    + '&h=' + $("#container").height() + '&zc=1');

Удивительно, но я обнаружил, что даже когда javascript ожидает загрузки всей страницы, запрос на изображение по-прежнему вызывает новый запрос! Является ли это известной ошибкой в ​​Firefox и Chrome, или что-то плохое jQuery ajax делает?

явно очевидно, что это не браузер ошибка.

Компьютер детерминирован и делает то, что именно вы ему рассказываете (не хотите, чтобы вы этого хотели). Если вы хотите кэшировать изображения, это делается на стороне сервера. Основываясь на том, кто обрабатывает кеширование, он может обрабатываться как:

  • Сервер (например, IIS или Apache) - обычно кэширует вещи, которые часто используются повторно (например: 2ce через 5 секунд).
  • Кэш приложения на стороне сервера - обычно он повторно использует пользовательский кеш сервера или создает спрайт изображения или...
  • Кэш браузера - сторона сервера добавляет заголовки кеша к изображениям и браузеру поддерживает кеш

Если это не ясно, я хотел бы дать понять: Вы не кэшируете изображения с помощью javascript.

В идеале я бы надеялся, что ajax не сделает второй запрос вообще, поскольку он запрашивает точно такой же URL-адрес.

Что вы пытаетесь сделать, это предустановить изображения.

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

Итак, чтобы делать предварительные изображения, все, что вам нужно сделать, это загрузить их в браузер. Если вы хотите, чтобы предварять кучу изображений, это, вероятно, лучше всего сделать это с помощью javascript, поскольку он обычно не будет поддерживать загрузку страницы когда сделано из javascript. Вы можете сделать это вот так:

function preloadImages(array) {
    if (!preloadImages.list) {
        preloadImages.list = [];
    }
    for (var i = 0; i < array.length; i++) {
        var img = new Image();
        img.onload = function() {
            var index = preloadImages.list.indexOf(this);
            if (index !== -1) {
                // remove this one from the array once it loaded
                // for memory consumption reasons
                preloadImages.splice(index, 1);
            }
        }
        preloadImages.list.push(img);
        img.src = array[i];
    }
}

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"]);

Затем, как только они были предварительно загружены с помощью javascript, браузер будет иметь их в своем кеше, и вы можете просто ссылаться на обычные URL-адреса в других местах (на ваших веб-страницах), и браузер будет извлекать этот URL из его кеш, а не через сеть.

Источник: Как кэшировать изображение в Javascript

Есть ли причина, по которой css и ajax в этом случае обычно имеют разные кеши, как будто браузер использует различное хранилище кеша для запросов css vs ajax?

enter image description here

Даже в отсутствие информации не поддавайтесь выводам!

Одна из основных причин использования предварительной загрузки изображений - если вы хотите использовать изображение для фонового изображения элемента на событии mouseOver или: hover. Если вы используете только фоновое изображение в CSS для: hover состояние, которое не будет загружаться до первого события: hover и, таким образом, будет короткая раздражающая задержка между движением мыши над этим область и изображение, которое на самом деле отображается.

Техника # 1 Загрузите изображение в обычное состояние элемента, только сдвиньте его с фоновой позицией. Затем переместите фон

чтобы отобразить его при наведении курсора.

#grass { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background-position: bottom left; }

Техника № 2 Если элемент, о котором идет речь, уже имеет фоновое изображение, и вам нужно изменить это изображение, выше

не будет работать. Как правило, вы должны искать спрайт здесь (комбинированный фоновое изображение) и просто сдвиньте положение фона. Но если это невозможно, попробуйте это. Применить фоновое изображение на другую страницу который уже используется, но не имеет фонового изображения.

#random-unsuspecting-element { 
    background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }

Идея создания новых элементов страницы, используемых для этой техники предварительной загрузки может появиться в вашей голове, например # preload-001, # preload-002, но это а не против стандартов веб-стандартов. Следовательно, использование страницы элементы, которые уже существуют на вашей странице.

Ответ 9

Браузер сделает 2 запроса на странице, потому что изображение, вызванное из css, также использует запрос get (не ajax), прежде чем отобразить всю страницу.

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

Если вы хотите загрузить изображение после загрузки всей страницы, u следует использовать document.ready() вместо