在html5浏览器中取消单个图像请求

时间:2011-02-07 20:32:29

标签: javascript jquery image canvas mobile-safari

我正在动态加载(大)图像以绘制到html5画布中,如下所示:

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

但每隔一段时间就会完全取消图像请求

我想出的唯一方法是将src设置为''。即。

t.src = ''

这适用于许多浏览器,但似乎只有Firefox实际上取消了对图像的http请求。

我通过禁用缓存并启用“模拟调制解调器速度”,使用Fiddler2对此进行了测试。然后运行a fiddle to test canceling a image request.(我很想听听关于如何测试这个的其他想法)

我知道有办法取消所有请求(as in this question),但我只想取消一个请求。

有关其他方式(特别是在移动浏览器上)的任何想法吗?

4 个答案:

答案 0 :(得分:13)

这是我设法让它在所有现代浏览器(Chrome,Safari,Mobile-Safari,Firefox和IE9)中运行的唯一方式。

  • 加载一个空的隐藏iframe
  • image tag附加到body
  • 中的iframe
  • img.onload完成时,您可以使用该图像dom元素绘制到带有drawImage()的html5画布
  • 如果您要取消加载,请在stop()的{​​{1}}(或IE中iframe上的contentWindow)发出execCommand("stop", false)。< / LI>
  • 取消图片加载后,您可以重复使用iframe加载更多图片。

我为此创建了一个类,并将coffeescript代码(以及它的已编译的javascript)放在github上: Cancelable Html5 Image Loader

如果你想玩它,我也创建了一个jsfiddle to test it out。记得启动Fiddler2(或类似的东西),看看实际的网络请求是否真的被取消了。

答案 1 :(得分:4)

您可以尝试使用window.stop()来停止所有请求,但不能停止单个请求。在IE中,它不是window.stop()它是document.execCommand(“Stop”,false)。

如果你有其他的东西按要求进行,那么这样做会干扰它。 (您可以通过重新请求您仍然需要的资源进行跟进,但这非常类似于努力工作)。


因此,如果您想停止对大图像的单个请求,您可以做的是将图像加载到隐藏的IFRAME中的文档中。 IFRAME的onload事件可用于将映像加载到主文档中,此时它应该被缓存(假设您已配置缓存指令)。

如果图像花费的时间过长,则可以访问IFRAME的contentWindow并发出停止命令。

您需要拥有与可以同时请求的图像一样多的IFRAME元素。

答案 2 :(得分:2)

我怀疑是否有一种跨浏览器的方式可以在没有黑客的情况下实现这一目标。一个建议是向服务器端脚本发出AJAX请求,该脚本返回图像的Base64编码版本,然后您可以将其设置为src属性。然后,如果您决定取消加载图像,则可以取消此请求。如果你想逐步显示图像,这可能会很困难。

答案 3 :(得分:2)

我实际上遇到了同样的问题并进行了一些测试。

我已经使用 iframe 进行了一些测试并取得了一些成功。在Firefox 3.6和Chrome上测试过。对于测试,我使用 9张15Mb 的图像。使用img预加载我几次杀了我的firefox(是的,在这台计算机上没有多少memoty),使用img“暂停”操作不会阻止图像加载如果请求已经开始,iframes挂起动作真的停止下载(因为我删除iframe)。下一步将使用 XMLHttpRequests 进行测试。由于此版本的测试代码使用braowser缓存行为形成图像URL以防止第二次加载,这也适用于ajax请求。但也许使用iframe我可以找到一种方法直接从iframe中加载的图像中检索二进制数据(限制在相同的域名网址上)。

这是我的测试代码(在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');
            });
    });
});

修改,然后填写以进行测试:http://jsfiddle.net/wPr3x/