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

IT技术 javascript jquery image canvas mobile-safari
2021-03-08 02:04:24

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

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

但每隔一段时间就想彻底取消图像请求

我想出的唯一方法是设置src''. IE

t.src = ''

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

通过禁用缓存和启用“模拟调制解调器速度”使用Fiddler2对此进行了测试然后运行小提琴来测试取消图像请求。(我很想听听其他关于如何测试这个的想法)

我知道有多种方法可以取消所有请求(如本问题所示),但我只想取消一个。

关于其他方式(尤其是在移动浏览器上)的任何想法?

4个回答

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

  • 加载一个空的和隐藏的 iframe
  • 追加了image tagbodyiframe
  • img.onload完成时,您可以使用图像DOM元素提请与HTML5画布drawImage()
  • 如果要取消的负荷,发出stop()iframecontentWindow(或execCommand("stop", false)contentDocumentIE中)。
  • 取消图像加载后,您可以重复使用 iframe 来加载更多图像。

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

如果你想玩它,我还创建了一个jsfiddle 来测试它请记住启动 Fiddler2(或类似的东西)以查看实际的网络请求是否真的被取消了。

+1 感谢您的黑客攻击。找到一种方法为没有画布的旧 IE 版本提供一些东西会很好,也许使用在 IE 上添加画布支持的库。
2021-05-10 02:04:24
@Amir,我们如何将其实现到 openlayers tile 请求中?
2021-05-15 02:04:24
@Amir 我遇到了同样的问题并试图复制你的脚本,但我无法让 iframe.contentWindow.stop() 方法工作。有什么办法可以看一下吗?
2021-05-18 02:04:24

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

如果您在请求方面有其他事情要做,那么这样做会干扰它。(您会跟进重新请求您仍然需要的资源,但这太像艰苦的工作了)。


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

如果图像花费的时间太长,那么您可以访问 IFRAME 的 contentWindow 并对其发出停止命令。

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

“但不是个人的”......你能支持吗?您提供的其余信息已在问题中说明并链接到。
2021-05-11 02:04:24
您只能停止该窗口正在进行的所有请求。这给了我一个想法,请参阅添加到我的答案中的其他信息!
2021-05-17 02:04:24

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

那是个很好的观点。当我提出这个想法时,我没有考虑开销。显然,在使用 AJAX nagoon97.wordpress.com/2008/04/06/...读取二进制文件方面已经做了一些努力我自己从未尝试过,但您可以这样做,然后使用<canvas>.
2021-05-03 02:04:24
好主意,但有一些与此相关的问题。首先是传输的数据量增加了 33%。(base64:24 位 -> 32 位)。然后(尤其是在移动浏览器上),它给 javascript 带来了很大的内存压力,因为数据必须作为字符串存储在 JS 中,然后它还有一个额外的 base64 解码步骤。对于大文件 (200K+),这可能会造成伤害。但这在某些情况下肯定可以很好地工作。
2021-05-10 02:04:24

我实际上有同样的问题并做了一些测试。

我已经用iframe进行了一些测试并取得了一些成功。在 Firefox 3.6 和 Chrome 上测试。对于测试,我使用了9 张 15Mb 的图像通过 img 预加载,我多次杀死了我的 Firefox(是的,这台计算机上没有太多内存),如果请求已经开始,使用 img 的“暂停”操作不会阻止图像加载,而 iframe 的暂停操作确实会停止下载(因为我删除 iframe)。下一步将使用XMLHttpRequests进行测试由于我的这个版本的测试代码使用了图像 url 中的 braowser 缓存行为来防止第二次加载,这也适用于 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');
            });
    });
});

编辑,这里是 fillde 来测试它:http : //jsfiddle.net/wPr3x/

这么近,但有一个问题。出于某种原因,当图像加载到 iframe 中时,它不会立即在缓存中可用。所以图像最终被加载了两次。这是一个可以玩的小提琴。 jsfiddle.net/amirshim/na3UA启动fiddler2(在 PC 上)并查看图像是如何被请求两次的。如果您关闭use_unique_name,那么您会看到在第一次加载整个页面后图像正在被缓存。
2021-04-29 02:04:24
正如在另一个问题中回答的那样,我认为如果你像我一样写它可以工作:-)。这是一个测试它的小提琴,但有时要小心更改图像 url,以防止目标服务器上的 DOS。jsfiddle.net/wPr3x
2021-05-10 02:04:24
我做loader.onload =而不是 jquery load()但是这里有一个 jQuery 方法,它有同样的问题:jsfiddle.net/amirshim/na3UA/1
2021-05-14 02:04:24
我创建了一个新问题来尝试解决该问题:stackoverflow.com/questions/4981229/...
2021-05-19 02:04:24
在第一个小提琴示例中,我没有看到在设置 src 属性之前和插入 iframe 之后在哪里设置 load() 回调。因此,您可能会在“about:blank”之类的加载之后立即调用此加载事件,即空的 iframe 基础源。
2021-05-20 02:04:24