2013-04-01 64 views
0

我有一个页面,我从YouTube获取提要,然后在此页面上显示。每行有4行,每行对应3个YouTube视频。我从youtube feed本身获得这些图片链接。与jquery同步发送图像请求

我想要实现的是在渲染这些图像时,我想一次从一行中的YouTube上获取图像。如果图像加载没有完成,我想等到下一行图像被提取。

有人能指导我如何做到这一点吗?我读了关于jQuery延期对象和回调的东西,但是因为我没有强大的jquery/js无法真正破解这一个。 js异步执行,因此所有图像请求都会一个接一个地执行,并且无法让js等待,直到每行的图像在下一行发送前完全呈现。

我有一个对当前循环和diaply图片如下:

$j("#thumbnail_image_"+i).css({'background-image':'url('+cdnPath+')'}); 
myImage[i].src = cdnPath; 
+0

为什么你同时设置img.src和background-image? – Tommi

回答

0

基本上,如果你使用正确的IMG元素来存储图片,您可以订阅它的onload和onerror的事件。然后,你可以算一下图片的许多人已经加载

var loaded = 0; 
for (var i = 0; i < imgtags.length; i++) { 
    imgtags[i].src = "/path/to/img"; 

    function handle() { 
     loaded++; 
     if (loaded == imgtags.length) { 
      loaded = 0; 
      // call next row or finish 
     }; 
    }; 
    img.onload = handle; 
    img.onerror = function() { 
     handle(); 
     // possible error handling here 
    }; 
}; 

其中imgtags是数组当前行中IMG元素。不要忘记在每一行中将count设置为0。因此你不需要JQuery。

如果你不使用IMG元素并为div设置背景,我认为它不可能实现。

Demo

+0

这不起作用。即使图像未完全加载,JS执行也不会停止,因为它是异步的。对于上面的代码,如果我的网络速度很慢,并且需要10秒才能完全下载图像,则第二行将不会显示。 –

+0

很难重现“慢速网络”,但我没有看到为什么10秒加载会影响此代码的原因。你可以解释吗? – Tommi

+0

我已经添加了小提琴,对于常规网络它的工作原理,当然你应该用递归加载代替最后的嵌套调用。 – Tommi

0

如果你想这样做,与Deferreds /许诺,那么,你可以这样做如下:

$(function() { 
    function loadRow($imgs, timeout) { 
     var dfrd = $.Deferred(), 
      n = 0; 
     $imgs.each(function() { 
      this.onload = function() { 
       if(++n == $imgs.length) { dfrd.resolve(); } 
      } 
      this.src = "/path/to/img"; 
     }); 
     setTimeout(dfrd.resolve, timeout);//in case of slow network or img.onload failure 
     return dfrd.promise(); 
    } 

    var $images = $(img.whatever),//adjust as required 
     rowlength = 5,//adjust as required 
     rowFilter = function(i) { 
      return function(index) { 
       return (index > i * rowlength) && (index < (i+1) * rowlength); 
      } 
     }, 
     nRows = Math.ceil($images.length/rowlength); 
     timeout = 10000,//(ms) adjust as required 
     d = $.Deferred().resolve(); 
    for(var i=0; i<nRows; i++) { 
     var $imgs = $images.filter(rowFilter(i)); 
     d = d.then(loadRow($imgs, timeout)); 
    } 
}); 

未经检验

loadRow()负载一行,并返回一个该行在加载或超时时已解决的Promise。

的代码的其余部分:

  • 建立用于图像的装置,以由行索引来选择。
  • 建立了一个种子Deferred,它立即解析以允许加载过程开始。
  • 建立了几个其他的变量。
  • 循环遍历行建立一个.then()链,它随着它的进展调用loadRow()

.then()链是控制行加载顺序的机制。

该代码比其他答案中的代码体积更大,但它对于您来说也稍微多一点,因为它包含超时机制。如果您有更简洁的方法选择每一行中的图像,它将会简化。