如何在不使用 window.stop() 的情况下中止图像 <img> 加载请求

IT技术 javascript jquery html ajax image
2021-02-19 13:33:13

我有一个很长的页面,可以在用户滚动时动态加载图像。

但是,如果用户从页面的某个部分快速滚动离开,我不希望图像继续加载到页面现在不在视图中的部分。

除了图像加载之外,页面上还会同时发生许多其他请求,因此在滚动事件上触发的生硬 window.stop() 是不可接受的。

我尝试删除并清除不再可见的图像的 img src 属性,但是,由于请求已经开始,图像继续加载。

请记住,当用户短暂地滚动经过页面的那部分时,图像 src 已被填充。但是,一旦过去,我无法在不使用 window.stop() 的情况下停止加载该图像。清除 src 不起作用。(铬 & FF)

我发现类似的帖子很接近,但似乎没有解决这个问题:

6个回答

正如nrabinowitz所提到的,您尝试做的是错误的方法您不能只是“取消”图像的加载过程(将src属性设置为空字符串不是一个好主意)。事实上,即使你可以,这样做只会让事情变得更糟,因为你的服务器会不断发送会被取消的数据,增加它的负载因子并减慢它的速度。另外,请考虑:

  1. 如果您的用户疯狂地上下滚动页面,他/她会期望一些加载延迟。
  2. 在开始加载页面的一部分之前有一个超时延迟(例如:200 毫秒)是可以接受的,并且在您的页面上的 200 毫秒间隔之后会停止和跳跃多少次?即使它发生了,它也会回到第 1 点
  3. 你的图片有多大?即使是速度较慢的服务器,每秒也可以提供大约几十个 3Kb 的缩略图。如果您的网站有更大的图像,请考虑使用带有LightBox 等组件的低分辨率和高分辨率图像

通常,计算机问题只是设计问题。

**编辑**

这是一个想法:

  1. 您的页面应显示DIV具有预期图像大小的宽度和高度的容器(使用 CSS 设置样式)。在 each 里面DIV,添加一个链接。例如 :

    <div class="img-wrapper thumbnail">
       <a href="http://www.domain.com/path/to/image">Loading...</a>
    </div>
    
  2. 添加这个 Javascript(未经测试,这个想法是自我描述的)

    $(function() {
    
    var imgStack;
    var loadTimeout;
    
    $(window).scroll(function() {
       imgStack = null;
       if (loadTimeout) clearTimeout(loadTimeout);
    
       loadTimeout = setTimeout(function() {
    
          // get all links visible in the view port
          // should be an array or jQuery object
          imgStack = ...
    
          loadNextImage();
       }, 200);                // 200 ms delay
    });
    
    function loadNextImage() {
       if (imgStack && imgStack.length) {
          var nextLink = $(imgStack.pop());   // get next image element
    
          $('<img />').attr('src', nextLink.attr('href'))
            .appendTo(nextLink.parent())
            .load(function() {
               loadNextImage();
            });
    
          // remove link from container (so we don't precess it twice)
          nextLink.remove();
       }
    };
    
    });
    
只需在滚动区域使用更好的压缩图像,在悬停时使用更高质量的图像,或者如果用户停止更长时间(一次加载一个图像在队列中)
2021-04-23 13:33:13
空 img src 不再是一个问题,如上面链接的博客文章末尾所述:更新(2009 年 12 月 2 日):似乎 <img src=""> 已在 Firefox 3.5 中修补(错误 444931)
2021-04-24 13:33:13
无论如何,您如何在滚动时加载图像?
2021-04-25 13:33:13
我们的 UI 促进浏览,用户希望在滚动时加载照片,并且在用户将手指移回滚动轮/触控板顶部时通常会发生 200 毫秒的延迟,即使意图是连续滚动。每一次偶然的停顿都会导致照片加载,在为低带宽场景设计时,随着加载队列不断变大,可能会导致用户等待很长时间。话虽如此,停止负载是错误的,您是对的,感谢您向我展示这个src问题。我想我只需要更聪明地了解我加载的照片数量和时间。
2021-05-03 13:33:13

嗯,我的想法:

1) 对图片发起AJAX请求,如果成功,图片进入浏览器缓存,一旦你设置了'src'属性,图片就会从缓存中显示出来

2) 您可以中止 XHR

我写了一个微型服务器,快速模拟巨大的图像下载(它实际上只等待 20 秒,然后返回一个图像)。然后我在我的 HTML 中有这个:

<!DOCTYPE html>
<html>
    <head>
        <style>
            img {
                width: 469px;
                height: 428px;
                background-color: #CCC;
                border: 1px solid #999;
            }
        </style>
    </head>

    <body>
        <img data-src="./img" src="" />
        <br />
        <a id="cancel" href="javascript:void(0)">CANCEL</a>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(function () {
                var xhr, img = $('img'), src = img.data('src');

                xhr = $.ajax(src, {
                    success: function (data) { img.attr('src', src) }
                });

                $('#cancel').click(function (){
                    xhr.abort();
                })
            });
        </script>
    </body>
</html>

您可以使用 ajax 调用加载图像,如果使用滚出,您可以中止调用。
在 jQuery 伪代码中,它会是这样的(请原谅我的语法错误,这只是一个例子):

1) 标记要加载的图像

$(".image").each( function(){
    if ( is_in_visible_area(this) ) { // check [1] for example
        $(this).addClass("load_me");
    } else {
        $(this).addClass("dont_load");
    }
});

2)加载图像

ajax_requests = {};

$(".image.load_me").each( function(){
    // load image
    var a = $.ajax({
        url: 'give_me_photos.php',
        data: {img: photo_id},
        success: function(html){
            photo_by_id(photo_id), img.append(html);
        }
    });
    ajax_requests[photo_id] = a;

});

3) 取消从屏幕加载那些

for( id in ajax_requests ) {
    if ( ! is_in_visible_area(id) ) {
        ajax_requests[id].abort();
    }
}

当然,还要添加一些检查图像是否已经加载(例如类“加载”)

[1]。滚动后检查元素是否可见

[2]。使用 jQuery 中止 Ajax 请求

这种方法不起作用,因为 .each 只会附加一次。您需要一个 onscroll 事件来重新检查图像可见性,理想情况下不应循环遍历 dom 中的所有图像,因为性能会变差。
2021-05-15 13:33:13

顺便说一句,另一个可能有用的想法:

1) 创建一个新的 iframe

2) 在 iframe 内部有开始加载图像的脚本,一旦加载,调用.parent's 方法

3) 需要时,停止使用.stopiframe 对象加载 iframe 内容

  1. 使用堆栈来管理 ajax 请求(意味着您将使用串行加载而不是并行加载,但这是值得的)

  2. 滚动停止时,等待 300 毫秒,然后将视图区域内的所有图像推入堆栈

  3. 每次用户滚动检查堆栈是否正在运行。(仅供参考 - 您可以停止对特定 url 的所有请求,而不是终止所有 ajax 调用。您也可以使用正则表达式,因此它不应停止页面上的任何其他请求)

  4. 如果现有堆栈正在运行 - 弹出除最顶部的图像之外的所有图像。

  5. 在所有 ajax 调用中 - 绑定 beforeSend() 事件以从堆栈中删除该特定图像

现在已经晚了,但我们在工作中做了一些非常相似的事情——如果你需要详细的代码,请告诉我。

干杯!