如何在不使用window.stop()的情况下放弃image <img>加载请求
我有一个非常长的页面,dynamic加载图片作为用户滚动浏览。
但是,如果用户从页面的某个部分快速滚动,我不希望图像继续加载到页面的现在的视图外部分。
除了图片加载之外,页面上还有很多其他请求发生,所以不能接受滚动事件触发的blunt window.stop()。
我已经尝试删除和清除不再可见的图像的img src属性,但是,由于请求已经启动,图像将继续加载。
请记住,当用户简单地滚动页面的那一部分时,图像src被填充。 一旦过去了,我不能不使用window.stop()停止加载该图像。 清除src没有工作。 (Chrome&FF)
类似的post我发现,接近,但似乎并没有解决这个问题:
- 停止使用JavaScript(lazyload)加载图像?
- Javascript:取消/停止图片请求
- 如何取消加载的图像
正如nrabinowitz所提到的,你所要做的是错误的做法。 你不能只是“取消”图像的加载过程(设置src
属性为空string不是一个好主意 )。 事实上,即使可以,这样做也只会使事情变得更糟,因为服务器会不断发送可能会被取消的数据,从而增加其负载因数并减慢速度。 另外,请考虑这一点:
- 如果你的用户在页面上上下滚动,他/她会预期一些加载延迟。
- 在开始载入页面的一部分之前有一个超时延迟(例如:200毫秒)是相当可接受的,在页面上以200毫秒的时间间隔之后停止和跳转多less次? 即使是这样,它回到了第一点
- 你的形象有多大? 即使是一台速度慢的服务器,每秒钟也能处理几十个3Kb的thunbnails。 如果您的网站有更大的图像,请考虑使用像lightBox这样的组件的低分辨率和高分辨率图像
计算机问题往往只是devise问题。
** 编辑 **
这是一个想法:
-
你的页面应该显示
DIV
容器的宽度和高度的预期图像大小(使用CSS风格)。 在每个DIV
内部添加一个链接。 例如 :<div class="img-wrapper thumbnail"> <a href="http://www.domain.com/path/to/image">Loading...</a> </div>
-
添加这个Javascript(未经testing,这个想法是自我描述的)
$(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)发起一个AJAX请求的图像,如果成功,图像进入浏览器caching,一旦你设置了'src'属性,图像显示从caching
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请求
-
使用堆栈来pipe理Ajax请求(意味着你将有串行加载而不是并行,但它是值得的)
-
在滚动停止时,等待300ms,然后将视图区域内的所有图像压入堆栈
-
每次用户滚动检查堆栈是否正在运行。 (你可以停止所有的请求到一个特定的URL而不是杀死所有的Ajax调用,也可以使用正则expression式,所以它不应该停止页面上的任何其他请求)
-
如果一个现有的堆栈正在运行 – popup所有的图像,除了最上面的图像。
-
在所有的Ajax调用 – 绑定beforeSend()事件从堆栈中删除特定的图像
现在已经很晚了,但是我们做了一些非常类似的工作 – 如果你需要详细的代码,请告诉我。
干杯!
也许你可以通过一个PHP脚本来检查图像,这将检查数据库中的字段(或更好的是一个memcached),将指示停止加载。 该脚本会将图像分成块,并在每个块之间暂停,并检查特定请求的停止标志是否是。 如果设置为发送A 204没有内容的头,一旦浏览器得到它将停止接收。
尽pipe这可能有点过分。
解决scheme可能是一个webworker。 一个webworker可以被终止,并与他连接。 但有一个小问题,webworker使用浏览器的有限连接,所以应用程序将被阻止。
现在我正在与serviceWorkers解决scheme – 他们没有连接限制(我希望如此)
顺便说一句,可能工作的另一个想法:
1)创build一个新的iframe
2)iframe内部有脚本开始加载图像,一旦加载,调用.parent
的方法
3)需要时,使用iframe对象上的.stop
停止iframe内容加载