Отменить один запрос изображения в браузерах html5 - PullRequest
21 голосов
/ 07 февраля 2011

Я загружаю (большие) изображения динамически, чтобы рисовать на холст html5, что-то вроде этого:

var t = new Image();
t.onload = ...
t.src = 'http://myurl';

Но время от времени хотелось бы отменить запрос изображения полностью.

Единственный способ, которым я придумал, это установить src в ''.то есть

t.src = ''

Это работает во многих браузерах, но кажется, что только Firefox фактически отменяет запрос http для изображения.

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

Я знаю, что есть способы отменить все запросы ( как в этом вопросе ), но я бы хотел отменить только один.

Есть какие-нибудь идеи относительно других способов (особенно в мобильных браузерах), чтобы сделать это?

Ответы [ 4 ]

13 голосов
/ 03 марта 2011

Только так мне удалось заставить его работать во всех современных браузерах (Chrome, Safari, Mobile-Safari, Firefox и IE9).

  • Загрузить пустой и скрытый iframe
  • добавить image tag к body в iframe
  • когда img.onload завершится, вы можете использовать этот элемент изображения dom для рисования на холсте html5 с drawImage()
  • Если вы хотите отменить загрузку, введите stop() для iframe contentWindow (или execCommand("stop", false) для contentDocument в IE).
  • после отмены загрузки изображения вы можете повторно использовать iframe для загрузки дополнительных изображений.

Я создал для этого класс и поместил код coffeescript (и это скомпилированный javascript) на github: Отменяемый загрузчик изображений HTML5

Если вы хотите поиграть с ним, я также создал jsfiddle, чтобы проверить его . Не забудьте запустить Fiddler2 (или что-то подобное), чтобы увидеть, что фактический сетевой запрос действительно отменяется.

4 голосов
/ 09 февраля 2011

Вы можете попробовать window.stop (), чтобы остановить все запросы, но не отдельные. В IE это не window.stop (), а document.execCommand («Stop», false).

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

<Ч />

Так что, если вы хотите остановить один запрос на большое изображение, вы можете загрузить изображение в документ в скрытом фрейме. Событие onload IFRAME можно использовать для загрузки изображения в основной документ, к которому время должно быть кэшировано (при условии, что для этого настроены директивы кэширования).

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

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

2 голосов
/ 12 февраля 2011

У меня такая же проблема, и я провел несколько тестов.

Я провел несколько тестов с iframes и добился определенного успеха.Протестировано на Firefox 3.6 и Chrome.Для тестов я использовал 9 изображений 15Mb .С предварительной загрузкой img я несколько раз убивал свой firefox (да, на этом компьютере не слишком много пометок), используя img действие «suspend» не предотвращает загрузку изображения, если запрос запущен, с помощью iframes действие suspend действительно останавливает загрузку (так как яудалите фрейм).Следующим шагом будет тестирование с XMLHttpRequests .Поскольку эта версия моего тестового кода использует поведение кэша Браузера, сформируйте URL-адрес изображения, чтобы предотвратить повторную загрузку, и это работает также с запросами ajax.Но, возможно, с помощью iframes я мог бы найти способ извлечения двоичных данных из загруженного изображения в iframe напрямую (с ограничением на те же URL-адреса домена).

Это мой тестовый код (очень быстрый на Chrome, может убить ваш firefoxслишком много очень больших изображений):

// jQuery.imageload.shared.list contains an array of oversized images url
jQuery.each(imglist,function(i,imgsrc) {

    name = 'imageload-frame';
    id = name + "-" + i;
    // with img it is not possible to suspend, the get is performed even after remove
    //var loader = jQuery('<img />').attr('name', name).attr('id',id);
    var loader = jQuery('<iframe />').attr('name', name).attr('id',id); 

    //no cache on GET query taken from jQuery core
    // as we really want to download each image for these tests
    var ts = +new Date;
    // try replacing _= if it is there
    var ret = imgsrc.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
    // if nothing was replaced, add timestamp to the end
    imgsrc = imgsrc + ((ret == imgsrc) ? (imgsrc.match(/\?/) ? "&" : "?") + "_=" + ts : "");

    loader.css('display', 'none').appendTo('body');
    loader.after( jQuery('<a>')
            .text(' stop ')
            .attr('href','#')
            .click(function(){
                loader.remove();
                jQuery(this).text(' suspended ');
            })
    );

    // start the load - preload
    loader.attr('src',imgsrc);

    // when preload is done we provide a way to get img in document
    loader.load(function() {
        jQuery(this).next("a:first")
            .text(" retrieve ").unbind('click')
            .click(function() {
                var finalimg = jQuery('<img />');
                // browser cache should help us now
                // but there's maybe a way to get it direclty from the iframe
                finalimg.attr('src',loader[0].src);
                finalimg.appendTo('body');
            });
    });
});

edit и вот fillde для его проверки: http://jsfiddle.net/wPr3x/

2 голосов
/ 10 февраля 2011

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

...