使用 jQuery 懒加载在 Google Chrome 中时,动态生成的图片会被请求两次。

8
我有一个ashx文件处理程序,用于生成我的图片。
<img src="www.mywebsite.com/action/getimage.ashx?imageID=f8be4bf6&width=100&height=700&bgcolor=999" />

这一切都很好。
现在,我想使用延迟加载。使用这个jquery lazy loading plugin
所以我调整了我的html图片,像这样:
<img src="imageplaceholder.gif" original-data="www.mywebsite.com/action/getimage.ashx?imageID=f8be4bf6&width=100&height=700&bgcolor=999" />

并添加了以下脚本:

$(function() {
   $("img").lazyload();
});

我在Google Chrome开发者工具的网络选项卡中注意到有两个调用请求发送到这个文件处理程序。
我已经在这里创建了一个测试fiddle:链接。如果你在这个fiddle上向下滚动,你会看到在Google Chrome中加载图像时会发出两个图像请求。在Firefox和IE中,只需要一个调用就可以完成。
有没有办法避免这种行为?
更新:
以下标头设置在文件处理程序中:
[0] "Server"    "Microsoft-IIS/7.5"
[1] "Set-Cookie"    "lang=nl; expires=Tue, 04-Feb-2014 13:08:56 GMT; path=/"

响应对象的Expires属性是:

context.Response.Expires = 0

您能否也发布一下图像处理程序 ProcessRequest 的内容?这样做的原因是因为只有在使用图像处理程序 www.mywebsite.com/action/getimage.ashx?imageID=f8be4bf6&width=100&height=700&bgcolor=999 的情况下才会出现此行为,但如果是像 http://www.appelsiini.net/attachments/jquery.png 这样的静态图像,则只有一个调用。 - Andy Refuerzo
我也注意到了这一点。静态图像可以正常工作。在示例fiddle中使用的文件处理程序与我的解决方案中使用的文件处理程序不同。我尝试了在网上找到的不同文件处理程序,以查看问题是否不是我的代码。到目前为止,它们都有相同的问题。因此,我认为问题不会出现在图像处理程序本身上。 - ThdK
3个回答

10

我认为根本的问题在于Chrome没有缓存图片。在这个演示中,每次点击按钮时Chrome都会发出一个新的请求。

懒加载脚本会触发2个请求,因为它首先将图片预加载到一个私有的img元素中,然后再将图像URL分配给原始的img元素。

我建议在您的图像处理程序的响应中添加ExpiresCache-Control头,并添加Last-ModifiedETag头,以便Chrome可以缓存图片。(有关缓存的更多信息,请参见Caching Tutorial for Web Authors and Webmasters。)


更新:我建议在您的图像处理程序中添加类似以下代码(来自MSDN):

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);

如果它预加载图像,那么这不会打破(懒加载)的目的吗? - Andy Refuerzo
“pre”加载仅在图像实际可见时发生。我不知道懒加载插件的工作原理,但我可以说,当图像进入视口时,第一次调用和第二次调用都会被执行。我已经在我的图像处理程序中更新了响应的当前缓存标头。 - ThdK
@ThdK 实际上,您的评论突显了我的答案,即Chrome以不同的方式处理$(“img”).attr(“src”,“”)。 如果您查看插件的代码,第110行第115行是设置src属性值为图像处理程序URL的唯一位置。 在我的测试中,当执行这些行时,会发出图像请求。 唯一的区别是,在第110行之前,<img />被隐藏了。 - Andy Refuerzo
请查看我的更新 - context.Response.Expires = 0 的意思是该图像可以被缓存0分钟。 - Jeffery To

5

当发生这样的情况时,请确保您没有打开Chrome DevTools并选中了“禁用缓存”复选框。如果任何插件、设置或其他原因导致缓存被禁用,可能会发生同样的事情。


2
这实际上是导致我的问题的原因。谢谢让我检查!在开发工具中取消选中“禁用缓存”可以使一切正常工作,与插件无关 - 这将发生在任何类型的懒加载库中(在我的情况下是React内部)。 - easwee

3

看起来,Google Chrome对$("img").attr("src", "") 的处理与其他浏览器不同。

查看GitHub上的插件源代码并在Chrome中添加断点(逐步进行),当它将图像的 src 属性修改为 original-data 的值时,会调用图像处理程序。

虽然图像处理程序可能是问题所在(正如我之前所评论的那样),但我发现的解决方案是更改插件源代码的第115行,从

.attr("src", $self.data(settings.data_attribute));

为了

.attr("src", "data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==");

新值是一个1像素乘1像素透明GIF图像的base64编码字符串。
在您的测试代码片段中,在缩小后的版本中找到第二个出现的内容。
c.data(h.data_attribute)

并将其更改为

"data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="

它仍将调用两次,但第一次调用将微不足道(0kb?),其他浏览器不受此更改影响。


为什么这个答案被踩了?我已经在插件中进行了更改,然后我确实看到第二个调用仅针对1x1px。我将与这里的其他人讨论此选项,以查看我们是否可以执行此操作。我不是jquery专家,所以我无法真正找出为什么那行代码确实做了什么,以及更改它是否100%安全。因此,如果您们中任何人对此有其他意见,请告诉我!非常感谢您在此方面花费时间! - ThdK
我也很困惑Chrome为这个插件的行为如此,但我的想法是我们无法改变浏览器的行为,也无法改变图像处理程序,所以我们只剩下插件了。我也不是jQuery专家,如果你得出了这种行为的结论,请在这里发布它。 :) - Andy Refuerzo
至于负投票,我不知道为什么。我认为这是避免在Chrome中请求相同图像两次的最佳解决方案,除非您想更改您的懒加载插件(不要问我有什么替代品 - 我不使用任何)。 - Andy Refuerzo
@ThdK 可能被否定是因为建议的修复需要编辑插件,这是一种不太好的解决办法。例如,如果该插件正在从CDN检索,则无法进行此操作。这只是一个想法。我会点赞此答案,因为Andy为您尝试解决此问题付出了努力,但我认为这不是实际解决方案。 - Ben Carey
在这种情况下,您的意见是正确的,因为它与脚本提供图像无关。因此,我将撤下我的答案。可能是一个错误,尽管是一个非常奇怪的错误!! - Ben Carey
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接