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

时间:2011-08-03 16:13:07

标签: javascript jquery html ajax image

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

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

除了图像加载之外,页面上还有很多其他请求同时发生,所以在滚动事件上触发一个钝的window.stop()是不可接受的。

我试过删除&amp;但是,清除不再在视图中的图像的img src属性,因为请求已经开始,图像会继续加载。

请记住,当用户快速滚动浏览页面的那一部分时,图像src已填入。一旦过去,我无法在不使用window.stop()的情况下从停止加载中获取该图像。清除src不起作用。 (Chrome&amp; FF)

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

7 个答案:

答案 0 :(得分:17)

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

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

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

    ** 编辑 **

    这是一个想法:

    1. 您的页面应显示DIV个容器,其中包含预期图像大小的宽度和高度(使用CSS来设置样式)。在每个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();
         }
      };
      
      });
      

答案 1 :(得分:12)

好吧,我的想法:

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>

答案 2 :(得分:2)

您可以使用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]。 Check if element is visible after scrolling

[2]。 Abort Ajax requests using jQuery

答案 3 :(得分:1)

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

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

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

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

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

  6. 现在已经很晚了,但我们在工作中做了类似的事情 - 如果您需要详细的代码,请告诉我。

    干杯!

答案 4 :(得分:0)

BTW,另一个可能有用的想法:

1)创建一个新的iframe

2)iframe内部有开始加载图片的脚本,加载后,调用.parent方法

3)在需要时,使用iframe对象上的.stop停止加载iframe内容

答案 5 :(得分:0)

也许你可以通过一个php脚本来提供图像,这个脚本会检查数据库中的一个字段(或者更好的是memcached),它会指示停止加载。脚本会将图像分成块并在每个块之间暂停,并检查特定请求的停止标志是否为。如果已设置,则发送标题为A 204无内容,一旦浏览器获得它将停止接收。

虽然这可能有点过时了。

答案 6 :(得分:0)

解决方案可能是一个网络工作者。一个webworker可以终止并与他联系。 但是网络工作者使用浏览器的有限连接存在一个小问题,因此应用程序将被阻止。

现在我正在与serviceWorkers合作解决方案 - 他们没有连接限制(我希望如此)