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

时间:2022-09-04 09:04:32

I have a very long page that dynamically loads images as users scroll through.

我有一个很长的页面,当用户滚动浏览时动态地加载图像。

However, if a user quickly scrolls away from a certain part of the page, I don't want the images to continue loading in that now out-of-view part of the page.

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

There are lots of other requests happening on the page simultaneously apart from image loading, so a blunt window.stop() firing on the scroll event is not acceptable.

除了图像加载之外,页面上还同时发生了许多其他请求,因此不允许在滚动事件上启动钝窗口.stop()。

I have tried removing & clearing the img src attributes for images that are no longer in view, however, since the request was already started, the image continues to load.

我已经尝试删除和清除已不在视图中的图像的img src属性,但是,由于请求已经启动,图像继续加载。

Remember that the image src was filled in as the user briefly scrolled past that part of the page. Once past though, I couldn't get that image from stop loading without using window.stop(). Clearing src didn't work. (Chrome & FF)

请记住,当用户快速浏览页面的那一部分时,图像src被填充。但是,一旦通过,我就无法在不使用window.stop()的情况下从停止加载中获得该图像。清算src不起作用。(铬& FF)

Similar posts I found that get close, but don't seem to solve this problem:

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

7 个解决方案

#1


17  

What you are trying to do is the wrong approach, as mentioned by nrabinowitz. You can't just "cancel" the loading process of an image (setting the src attribute to an empty string is not a good idea). In fact, even if you could, doing so would only make things worst, as your server would continually send data that would get cancelled, increasing it's load factor and slow it down. Also, consider this:

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

  1. if your user scroll frenetically up and down the page, he/she will expect some loading delays.
  2. 如果您的用户在页面上上下滚动,他/她将会期待一些加载延迟。
  3. having a timeout delay (ex: 200 ms) before starting to load a portion of the page is pretty acceptable, and how many times will one stop and jump after 200 ms interval on your page? Even it it happens, it comes back to point 1
  4. 在开始加载页面的一部分之前有一个超时延迟(例如:200 ms)是可以接受的,在页面上间隔200 ms后一次停止和跳转的次数是多少?即使它发生了,它又回到点1。
  5. how big are your images? Even a slow server can serve about a few tens of 3Kb thunbnails per second. If your site has bigger images, consider using low and hi resolution images with some components like lightBox
  6. 你的照片有多大?即使是一台速度很慢的服务器,每秒也可以处理几十个3Kb的带宽。如果你的网站有更大的图片,考虑使用低分辨率和高分辨率的图片,比如lightBox

Often, computer problems are simply design problems.

通常,电脑问题只是设计问题。

** EDIT **

* *编辑* *

Here's an idea :

这里有一个想法:

  1. your page should display DIV containers with the width and height of the expected image size (use CSS to style). Inside of each DIV, add an link. For example :

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

    <div class="img-wrapper thumbnail">
       <a href="http://www.domain.com/path/to/image">Loading...</a>
    </div>
    
  2. Add this Javascript (untested, the idea is self describing)

    添加这个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();
       }
    };
    
    });
    

#2


12  

Well, my idea:

好吧,我的想法:

1) initiate an AJAX request for the image, if it succeeds, the image goes to the browser cache, and once you set the 'src' attribute, the image is shown from the cache

1)初始化对映像的AJAX请求,如果成功,映像将进入浏览器缓存,一旦设置了“src”属性,映像将从缓存中显示

2) you can abort the XHR

2)可以中止XHR

I wrote a tiny server with express emulating the huge image download (it actually just waits 20 seconds, then returns an image). Then I have this in my HTML:

我用express编写了一个小服务器来模拟巨大的图像下载(它实际上只需要等待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>

#3


2  

You can load your images using ajax calls, and in case that the uses scrolls-out, you can abort the calls.
In jQuery pseudo-code it would be something like that (forgive me mistakes in syntax, it is just an example):

您可以使用ajax调用加载映像,如果使用scrolls-out,则可以中止调用。在jQuery伪代码中,它应该是这样的(请原谅我语法错误,这只是一个例子):

1) tag images that you want to load

1)标记要加载的图像

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

2) load images

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) cancel loading those out of the screen

3)取消屏幕上的加载。

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

Of course, add also some checking if the image is already loaded (e.g. class "loaded")

当然,如果图像已经被加载,也可以添加一些检查(例如“已加载”类)

[1]. Check if element is visible after scrolling

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

[2]. Abort Ajax requests using jQuery

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

#4


1  

  1. Use a stack to manage ajax requests (means you will have serial loading instead of parallel but it is worth it)

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

  2. On scroll stop, wait for 300ms and then push all images inside view-area into stack

    在滚动停止时,等待300ms,然后将视图区域内的所有图像放入堆栈

  3. Every time a user scrolls check if a stack is running. (fyi - you can stop all requests to a particular url instead of killing all ajax calls. also you can use regex so it should not stop any other requests on the page)

    每次用户滚动时,都要检查堆栈是否正在运行。(fyi -您可以停止对特定url的所有请求,而不是终止所有ajax调用。也可以使用regex,因此它不应该停止页面上的任何其他请求。

  4. If an existing stack is running - pop all the images that are in it except for the top most one.

    如果一个现有的堆栈正在运行——弹出除最上面的图像之外的所有图像。

  5. On all ajax calls - bind beforeSend() event to remove that particular image from the stack

    在所有ajax调用中——绑定be前述()事件,从堆栈中删除特定的映像

It is late right now, but we have done something very similar at work - if you need the detailed code let me know.

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

Cheers!

干杯!

#5


0  

Maybe you could serve the image through a php script which would check a field in the the db (or better yet a memcached) that would indicate stop loading. the script would portion up the image into chunks and pause in between each chunk and check if the stop flag for the particular request is. If it is set you send the header with A 204 no content which as soon as the browser gets it will stop receiving.

也许您可以通过php脚本提供图像,该脚本将检查db(或者更好的是memcached)中的一个字段,该字段将指示停止加载。脚本将图像分成块,并在每个块之间暂停,检查特定请求的停止标志是否为。如果设置好了,你就发送一个204个no内容的标题,浏览器一旦接收到,标题就会停止接收。

This may be a bit over kill though.

这可能有点过头了。

#6


0  

The solution could be a webworker. a webworker can be terminated and with him the connection. But there is a small problem that the webworker uses the limited connections of the browser so the application will be blocked.

解决方案可能是网络工作者。一个网络工作者可以被终止和他的连接。但是有一个小问题,就是webworker使用浏览器有限的连接来阻止应用程序。

Right now I'm working on a solution with serviceWorkers - they don't have a connection limit (I hope so)

现在我正在与serviceWorkers一起研究一个解决方案——他们没有连接限制(我希望如此)

#7


-1  

BTW, another idea that might work:

顺便说一句,另一个可能行得通的想法是:

1) create a new iframe

1)创建一个新的iframe

2) inside of the iframe have the script that starts loading the image, and once it's loaded, call the .parent's method

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

3) when in need, stop the iframe content loading using .stop on the iframe object

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

#1


17  

What you are trying to do is the wrong approach, as mentioned by nrabinowitz. You can't just "cancel" the loading process of an image (setting the src attribute to an empty string is not a good idea). In fact, even if you could, doing so would only make things worst, as your server would continually send data that would get cancelled, increasing it's load factor and slow it down. Also, consider this:

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

  1. if your user scroll frenetically up and down the page, he/she will expect some loading delays.
  2. 如果您的用户在页面上上下滚动,他/她将会期待一些加载延迟。
  3. having a timeout delay (ex: 200 ms) before starting to load a portion of the page is pretty acceptable, and how many times will one stop and jump after 200 ms interval on your page? Even it it happens, it comes back to point 1
  4. 在开始加载页面的一部分之前有一个超时延迟(例如:200 ms)是可以接受的,在页面上间隔200 ms后一次停止和跳转的次数是多少?即使它发生了,它又回到点1。
  5. how big are your images? Even a slow server can serve about a few tens of 3Kb thunbnails per second. If your site has bigger images, consider using low and hi resolution images with some components like lightBox
  6. 你的照片有多大?即使是一台速度很慢的服务器,每秒也可以处理几十个3Kb的带宽。如果你的网站有更大的图片,考虑使用低分辨率和高分辨率的图片,比如lightBox

Often, computer problems are simply design problems.

通常,电脑问题只是设计问题。

** EDIT **

* *编辑* *

Here's an idea :

这里有一个想法:

  1. your page should display DIV containers with the width and height of the expected image size (use CSS to style). Inside of each DIV, add an link. For example :

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

    <div class="img-wrapper thumbnail">
       <a href="http://www.domain.com/path/to/image">Loading...</a>
    </div>
    
  2. Add this Javascript (untested, the idea is self describing)

    添加这个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();
       }
    };
    
    });
    

#2


12  

Well, my idea:

好吧,我的想法:

1) initiate an AJAX request for the image, if it succeeds, the image goes to the browser cache, and once you set the 'src' attribute, the image is shown from the cache

1)初始化对映像的AJAX请求,如果成功,映像将进入浏览器缓存,一旦设置了“src”属性,映像将从缓存中显示

2) you can abort the XHR

2)可以中止XHR

I wrote a tiny server with express emulating the huge image download (it actually just waits 20 seconds, then returns an image). Then I have this in my HTML:

我用express编写了一个小服务器来模拟巨大的图像下载(它实际上只需要等待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>

#3


2  

You can load your images using ajax calls, and in case that the uses scrolls-out, you can abort the calls.
In jQuery pseudo-code it would be something like that (forgive me mistakes in syntax, it is just an example):

您可以使用ajax调用加载映像,如果使用scrolls-out,则可以中止调用。在jQuery伪代码中,它应该是这样的(请原谅我语法错误,这只是一个例子):

1) tag images that you want to load

1)标记要加载的图像

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

2) load images

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) cancel loading those out of the screen

3)取消屏幕上的加载。

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

Of course, add also some checking if the image is already loaded (e.g. class "loaded")

当然,如果图像已经被加载,也可以添加一些检查(例如“已加载”类)

[1]. Check if element is visible after scrolling

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

[2]. Abort Ajax requests using jQuery

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

#4


1  

  1. Use a stack to manage ajax requests (means you will have serial loading instead of parallel but it is worth it)

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

  2. On scroll stop, wait for 300ms and then push all images inside view-area into stack

    在滚动停止时,等待300ms,然后将视图区域内的所有图像放入堆栈

  3. Every time a user scrolls check if a stack is running. (fyi - you can stop all requests to a particular url instead of killing all ajax calls. also you can use regex so it should not stop any other requests on the page)

    每次用户滚动时,都要检查堆栈是否正在运行。(fyi -您可以停止对特定url的所有请求,而不是终止所有ajax调用。也可以使用regex,因此它不应该停止页面上的任何其他请求。

  4. If an existing stack is running - pop all the images that are in it except for the top most one.

    如果一个现有的堆栈正在运行——弹出除最上面的图像之外的所有图像。

  5. On all ajax calls - bind beforeSend() event to remove that particular image from the stack

    在所有ajax调用中——绑定be前述()事件,从堆栈中删除特定的映像

It is late right now, but we have done something very similar at work - if you need the detailed code let me know.

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

Cheers!

干杯!

#5


0  

Maybe you could serve the image through a php script which would check a field in the the db (or better yet a memcached) that would indicate stop loading. the script would portion up the image into chunks and pause in between each chunk and check if the stop flag for the particular request is. If it is set you send the header with A 204 no content which as soon as the browser gets it will stop receiving.

也许您可以通过php脚本提供图像,该脚本将检查db(或者更好的是memcached)中的一个字段,该字段将指示停止加载。脚本将图像分成块,并在每个块之间暂停,检查特定请求的停止标志是否为。如果设置好了,你就发送一个204个no内容的标题,浏览器一旦接收到,标题就会停止接收。

This may be a bit over kill though.

这可能有点过头了。

#6


0  

The solution could be a webworker. a webworker can be terminated and with him the connection. But there is a small problem that the webworker uses the limited connections of the browser so the application will be blocked.

解决方案可能是网络工作者。一个网络工作者可以被终止和他的连接。但是有一个小问题,就是webworker使用浏览器有限的连接来阻止应用程序。

Right now I'm working on a solution with serviceWorkers - they don't have a connection limit (I hope so)

现在我正在与serviceWorkers一起研究一个解决方案——他们没有连接限制(我希望如此)

#7


-1  

BTW, another idea that might work:

顺便说一句,另一个可能行得通的想法是:

1) create a new iframe

1)创建一个新的iframe

2) inside of the iframe have the script that starts loading the image, and once it's loaded, call the .parent's method

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

3) when in need, stop the iframe content loading using .stop on the iframe object

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