Как работает предварительная загрузка javascript? - PullRequest
6 голосов
/ 14 мая 2009

Я не хочу знать способ предварительной загрузки изображений, я нашел много в сети, но я хочу знать, как это работает. Как JavaScript может предварительно загружать изображения? Я имею в виду, что я попробовал отсюда фрагмент, и даже если он работает, он не загружает изображения.

Когда я проверяю firebug, я вижу, что изображение загружается дважды, один раз во время предварительной загрузки, в другой раз при отображении!

Чтобы улучшить этот код, я хотел бы знать, как он работает.

Вот что я делаю:

 function preload(arrayOfImages) {
        $(arrayOfImages).each(function(){
            $('<img/>')[0].src = this;
            //(new Image()).src = this;
            alert(this +'  &&   ' + i++);

        });
    }

тогда я делаю что-то подобное:

preloader = function() {
    preload(myImages);
}

$(document).ready(preloader);

Вот как я могу отобразить / добавить изображение:

$("li.works").click(function() {
             $("#viewer").children().empty();
             $('#viewer').children().append('<img src=\'images/ref/'+this.firstChild.id+'.jpg\' alt="'+this.firstChild.id+'" \/>')
             $("#viewer").children().fadeIn();

Ответы [ 5 ]

11 голосов
/ 14 мая 2009

Ваш основной прелоадер Javascript делает это:

var image = new Image();
image.src = '/path/to/the/image.jpg';

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

Один интересный момент, который обсуждается в этом вопросе - это то, что происходит, когда у вас есть массив изображений и вы пытаетесь предварительно загрузить их все, используя один и тот же объект Image:

var images = ['image1.jpg','image2.jpg'];
var image = new Image();
for(var x = 0; x < images.length; x++) {
    image.src = images[x];
}

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

Таким образом, правильный способ сделать много одновременно:

var images = ['image1.jpg','image2.jpg'];
for(var x = 0; x < images.length; x++) {
    var image = new Image();
    image.src = images[x];
}
5 голосов
/ 08 октября 2011

Предварительная загрузка Javascript работает благодаря использованию механизма кэширования, используемого браузерами.

Основная идея заключается в том, что после загрузки ресурса он некоторое время хранится локально на клиентском компьютере, поэтому браузеру не нужно снова извлекать ресурс из сети, в следующий раз требуется для отображения / использования браузером.

Ваш код, вероятно, работает просто отлично, и вы просто неправильно понимаете, что отображает Fire Bug.

Чтобы проверить эту теорию, просто нажмите www.google.com с чистым кешем. То есть сначала очистите историю загрузок.

Первый раз через все, вероятно, будет иметь статус 200 ОК. Это означает, что ваш браузер запросил ресурс, а сервер отправил его. Если вы посмотрите на нижнюю часть окна Fire Bug, там будет указано, насколько большой была страница, скажем, 195 Кб, и какая часть этого была извлечена из кэша. В этом случае 0Kb.

Затем перезагрузите ту же страницу, не очищая кеш, и вы все равно увидите такое же количество запросов в FireBug.

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

Отличие состоит в том, что для большинства этих запросов сервер возвращал статус 304 Not Modified Status, поэтому браузер проверил свой кэш, чтобы убедиться, что ресурс уже сохранен локально, что в данном случае и с предыдущей страницы. нагрузки. Так что браузер просто вытащил ресурс из локального кэша.

Если вы посмотрите на нижнюю часть окна Fire Bug, вы увидите, что размер страницы все еще остается прежним (195 КБ), но что большая его часть, в моем случае 188 КБ, была локально извлечена из кэша.

Таким образом, кеш работал, и во второй раз, когда я нажал на Google, я сэкономил 188 КБ загрузки.

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

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

2 голосов
/ 14 мая 2009

Вас может смущать понятие «предзагрузка». Если у вас есть несколько изображений в вашем HTML с <img src="...">, они не могут быть предварительно загружены с помощью Javascript, они просто загружаются вместе со страницей.

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

Для большинства приложений, как правило, лучше использовать «спрайты CSS» в качестве формы предварительной загрузки вместо Javascript. У ТАК должно быть множество вопросов по этому вопросу.

1 голос
/ 14 мая 2009

Индекс в цикле только ищет на первом изображении. Измените это, чтобы использовать индекс:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(i){   // Note the argument
        $('<img/>')[i].src = this;    // Note the i
        //(new Image()).src = this;
        alert(this +'  &&   ' + i++);

    });
}

Редактировать: в ретроспективе это было неправильно, и я вижу, что вы пытаетесь создать элементы изображения. Я не понимаю, почему индекс вообще существует, индекс не обязательно должен быть. Я думаю, что функция должна выглядеть следующим образом:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img/>').attr('src', this);
    });
}    

И чтобы создать экземпляр, почему бы просто не сделать это:

$(function () {    // Equivalent to $(document).ready()
    preload(myImages);
});

Предварительная загрузка изображений JavaScript работает, потому что, когда создается элемент DOM, содержащий изображение, изображение загружается и кэшируется. Даже если будет сделан другой запрос, когда изображение фактически будет отображаться из HTML, сервер отправит обратно 304 (без изменений), а браузер просто загрузит изображение из своего кэша.

Паоло предлагает использовать следующие обозначения для создания объекта изображения:

var image = new Image();

Хотя это будет работать, DOM-совместимый способ сделать это:

var image = document.createElement('img');
image.setAttribute('src', 'path/to/image.jpg');

Как это делается в сценарии, за исключением того, что для этого используется литеральный синтаксис HTML строки jQuery. Кроме того, большинство современных браузеров предлагают совместимость с конструктором Image(), просто вызывая стандартные методы DOM. Например, если вы откроете консоль Google Chrome JavaScript и наберете Image, вы получите следующее:

function Image() {
    return document.createElementNS('http://www.w3.org/1999/xhtml', 'img');
}

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

1 голос
/ 14 мая 2009

Это просто включает создание нового объекта изображения DOM и установку атрибута src. Ничего умного и AFAIK, он всегда работал для меня.

Возможно ли, что второй загрузочный firebug показывает, загружает ли он его из кэша?

...