使用jQuery异步加载图片

146

我想使用jQuery异步加载页面上的外部图片,我已经尝试了以下方法:

$.ajax({ 
   url: "http://somedomain.com/image.jpg", 
   timeout:5000,
   success: function() {

   },
   error: function(r,x) {

   }
});

但它总是返回错误,像这样加载图像是否可能?

我尝试使用.load方法,它可以工作,但我不知道如何设置超时,如果图像不可用(404)。 我该怎么做?


这对我很有用:https://dev59.com/d2025IYBdhLWcg3wNTAV - MrRhoads
12个回答

205

无需使用ajax。您可以创建一个新的图像元素,设置其源属性,并在其加载完成后将其放置在文档中的某个位置:

var img = $("<img />").attr('src', 'http://somedomain.com/image.jpg')
    .on('load', function() {
        if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
            alert('broken image!');
        } else {
            $("#something").append(img);
        }
    });

20
超时和404错误应该如何处理? - Arief
8
如果您检查浏览器的时间轴,例如 Google Chrome 的开发者工具时间轴,您会发现创建任何 DOM 元素(无论是否将其附加到 DOM 中似乎都无关紧要),然后设置其源将其添加到当前文档的加载列表中 - 因此,页面直到该创建的元素被加载后才算“加载完成”。实际上,您的解决方案不是异步事件,因为直到图像加载完毕,window.load() 才会触发,可能推迟某些“绘制”或“布局”操作,并确定任何 onload 事件依赖项的延迟。 - Tom Auger
2
@TomAuger:那我们怎么才能真正实现异步呢?我刚用load()测试了一下代码,它并不是异步的。 - basZero
2
@gidzior,它在IE8中无法工作,因为您无法使用jquery设置IE8中的SRC属性。请参考此处:http://stackoverflow.com/questions/12107487/internet-explore-8-wont-change-image-src-with-attr - Rich
1
@Yamcha 这是有关在不传递URL作为第一个参数调用.load()的文档:http://api.jquery.com/load-event/。文档指出:“Ajax模块也有一个名为`.load()`的方法。哪个被触发取决于传递的参数集。”请注意,由于存在两个名为`.load()`的不同函数会让人们感到困惑(就像你一样!),因此仅使用`.load()`来绑定处理程序已被弃用,而应使用`.on('load', handler)`。我正在编辑答案以使用非弃用形式。 - Mark Amery
显示剩余10条评论

81

如果你确实需要使用Ajax...

我遇到过一些情况,其中onload处理程序不是正确的选择。在我的情况下,是通过javascript打印时。因此,对于这种情况,有两个选项可以使用Ajax风格:

解决方案1

使用Base64图像数据和REST图像服务。如果您有自己的Web服务,可以添加一个JSP/PHP REST脚本,以Base64编码提供图像。现在这有什么用?我发现了一个很酷的新语法用于图像编码:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE..."/>

你可以使用Ajax加载图像的Base64数据,然后在完成后构建Base64数据字符串以生成图像!非常有趣 :). 我建议使用这个网站http://www.freeformatter.com/base64-encoder.html进行图像编码。

$.ajax({ 
    url : 'BASE64_IMAGE_REST_URL', 
    processData : false,
}).always(function(b64data){
    $("#IMAGE_ID").attr("src", "data:image/png;base64,"+b64data);
});

解决方案2:

欺骗浏览器使用其缓存。这将在资源在浏览器缓存中时为您提供漂亮的fadeIn()效果:

var url = 'IMAGE_URL';
$.ajax({ 
    url : url, 
    cache: true,
    processData : false,
}).always(function(){
    $("#IMAGE_ID").attr("src", url).fadeIn();
});   

然而,这两种方法都有其缺点:第一种只适用于现代浏览器。第二种存在性能故障,并且依赖于如何使用缓存的假设。

祝好, will


1
如果当前浏览器支持状态对您来说是可接受的(http://caniuse.com/#search=Blob),则可以使用[Blobs](https://developer.mozilla.org/en-US/docs/Web/API/Blob)而不是数据URI。这种方法比使用base64编码的数据URI更加专业,也更节省内存(因为base64不是一种内存高效的格式),尽管后者在现实世界中大多数情况下可能并不重要。 - Mark Amery

13

使用jQuery,您可以简单地将“src”属性更改为“data-src”。图像不会被加载。但是位置将 标签一起存储。我喜欢这样。

<img class="loadlater" data-src="path/to/image.ext"/>
一个简单的jQuery代码将data-src复制到src,这将在需要时开始加载图片。在我的情况下是在页面完成加载后。
$(document).ready(function(){
    $(".loadlater").each(function(index, element){
        $(element).attr("src", $(element).attr("data-src"));
    });
});

我敢打赌jQuery代码可以缩写,但这样写也很容易理解。


4
提示:如果您正在使用data-标签,那么通过$(element).data('src')访问它们要比通过$(element).attr('data-src')更容易。请注意不要改变原文的意思。 - Maxim Kumpan
实际上,今天我不再使用jQuery了。但这是个人口味的问题,也取决于您正在构建的网站规模。但当下热门话题是“渐进式图像”,也许这是值得研究的东西。https://www.smashingmagazine.com/2018/02/progressive-image-loading-user-perceived-performance/ - htho

9
$(<img />).attr('src','http://somedomain.com/image.jpg');

使用此方法应该比ajax更好,因为如果它是一个图库,并且您正在浏览图片列表,如果图像已经在缓存中,它不会向服务器发送另一个请求。在jQuery/ajax情况下,它将发送请求并返回HTTP 304(未修改),然后如果原始图像已经存在于缓存中,则使用缓存中的原始图像。上述方法减少了在图库中第一次循环图像后向服务器发出空请求。


5
您可以使用延迟对象进行异步加载。
function load_img_async(source) {
    return $.Deferred (function (task) {
        var image = new Image();
        image.onload = function () {task.resolve(image);}
        image.onerror = function () {task.reject();}
        image.src=source;
    }).promise();
}

$.when(load_img_async(IMAGE_URL)).done(function (image) {
    $(#id).empty().append(image);
});

请注意:为避免缓存问题,必须在image.src之前使用image.onload。

3
这也可以运作...
var image = new Image();
image.src = 'image url';
image.onload = function(e){
  // functionalities on load
}
$("#img-container").append(image);

3

如果你只想设置图像的来源,可以使用以下方法。

$("img").attr('src','http://somedomain.com/image.jpg');

2
据我所知,您需要在此处执行.load()函数而不是.ajax()函数,但是您可以使用jQuery setTimeout使其保持活动状态(ish)。
<script>
 $(document).ready(function() {
 $.ajaxSetup({
    cache: false
});
 $("#placeholder").load("PATH TO IMAGE");
   var refreshId = setInterval(function() {
      $("#placeholder").load("PATH TO IMAGE");
   }, 500);
});
</script>

2
抱歉,我稍微误解了您的问题,我以为您正在加载不断变化的图像或其他内容(因此提到了Ajax)。 - benhowdle89

2
使用.load来加载您的图像。为了测试是否出现错误(比如404),您可以执行以下操作:
$("#img_id").error(function(){
  //$(this).hide();
  //alert("img not loaded");
  //some action you whant here
});

注意 - 当img标签的src属性为空时,.error()事件将不会被触发。


0

//Puedes optar por esta solución:

var img = document.createElement('img');
img.setAttribute('src', element.source)
img.addEventListener('load', function(){
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
                            alert('broken image!');
                        } else {
                        $("#imagenesHub").append(img);
                        }
                    });


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