Tải hình ảnh không đồng bộ với jQuery


142

Tôi muốn tải hình ảnh bên ngoài trên trang của mình một cách không đồng bộ bằng jQuery và tôi đã thử như sau:

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

   },
   error: function(r,x) {

   }
});

Nhưng nó luôn trả về lỗi, thậm chí có thể tải hình ảnh như thế này không?

Tôi đã thử sử dụng .loadphương thức và nó hoạt động nhưng tôi không biết làm thế nào tôi có thể đặt thời gian chờ nếu hình ảnh không có sẵn (404). Tôi có thể làm cái này như thế nào?


Điều này hoạt động với tôi: stackoverflow.com/questions/6150289/ trên
MrRhoads

Câu trả lời:


199

Không cần ajax. Bạn có thể tạo một thành phần hình ảnh mới, đặt thuộc tính nguồn của nó và đặt nó ở đâu đó trong tài liệu sau khi tải xong:

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
Làm gì với thời gian chờ và 404?
Arief

1
Làm thế nào để thiết lập thời gian chờ với điều này? Tôi đã thử phương pháp này nhưng không hiểu sao trang vẫn chờ hình ảnh tải.
Arief

7
Ví dụ: nếu bạn kiểm tra dòng thời gian của trình duyệt, ví dụ như dòng thời gian dành cho công cụ dev của Google Chrome, bạn sẽ thấy việc tạo bất kỳ phần tử DOM nào (dù bạn có đính kèm nó với DOM hay không đều không liên quan) và sau đó đặt nguồn của nó thêm vào tải của tài liệu hiện tại danh sách - vì vậy trang sẽ KHÔNG hoàn thành "tải" cho đến khi phần tử được tạo đó được tải. Giải pháp của bạn thực sự không phải là một sự kiện không đồng bộ theo nghĩa window.load () sẽ không kích hoạt cho đến khi hình ảnh được tải, có thể trì hoãn một số hoạt động painthoặc layouthoạt động nhất định và chắc chắn trì hoãn mọi onloadphụ thuộc sự kiện.
Tom Auger

2
@TomAuger: Vậy làm thế nào chúng ta có thể làm cho nó thực sự không đồng bộ? Tôi vừa kiểm tra mã với load () và nó KHÔNG đồng bộ.
basZero

2
@gidzior Nó không hoạt động trong IE8 vì bạn không thể đặt thuộc tính SRC trong IE8 bằng jquery. tham khảo tại đây: stackoverflow.com/questions/12107487/ Mạnh
Giàu

77

NẾU BẠN THỰC SỰ CẦN SỬ DỤNG AJAX ...

Tôi đã đi qua các giai đoạn mà các trình xử lý tải không phải là lựa chọn đúng đắn. Trong trường hợp của tôi khi in qua javascript. Vì vậy, thực sự có hai tùy chọn để sử dụng kiểu AJAX cho việc này:

Giải pháp 1

Sử dụng dữ liệu hình ảnh Base64 và dịch vụ hình ảnh REST. Nếu bạn có dịch vụ web của riêng mình, bạn có thể thêm tập lệnh REST / PHP REST cung cấp hình ảnh ở dạng mã hóa Base64. Bây giờ làm thế nào là hữu ích? Tôi đã bắt gặp một cú pháp mới thú vị để mã hóa hình ảnh:

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

Vì vậy, bạn có thể tải dữ liệu Image Base64 bằng Ajax và sau đó khi hoàn thành, bạn xây dựng chuỗi dữ liệu Base64 thành hình ảnh! Rất vui :). Tôi khuyên bạn nên sử dụng trang web này http://www.freeformatter.com/base64-encoder.html để mã hóa hình ảnh.

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

Giải pháp 2:

Lừa trình duyệt để sử dụng bộ đệm của nó. Điều này cung cấp cho bạn một fadeIn () đẹp khi tài nguyên nằm trong bộ đệm của trình duyệt:

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

Tuy nhiên, cả hai phương pháp đều có nhược điểm của nó: Cách thứ nhất chỉ hoạt động trên các trình duyệt hiện đại. Cái thứ hai có trục trặc về hiệu năng và dựa vào giả định cách sử dụng bộ đệm.

chúc mừng, sẽ


1
Nếu trạng thái hỗ trợ trình duyệt hiện tại được bạn chấp nhận ( caniuse.com/#search=Blob ), bạn có thể sử dụng Blobs thay vì URI dữ liệu. Điều này 'cảm thấy ít bị hack hơn so với sử dụng URI dữ liệu được mã hóa cơ sở64 và cũng ít lãng phí bộ nhớ hơn (vì cơ sở 64 không phải là định dạng hiệu quả bộ nhớ), mặc dù sau này có lẽ không quan trọng trong thế giới thực.
Đánh dấu Amery

11

Sử dụng jQuery, bạn có thể chỉ cần thay đổi thuộc tính "src" thành "data-src". Hình ảnh sẽ không được tải. Nhưng vị trí được lưu trữ với thẻ. Mà tôi thích.

<img class="loadlater" data-src="path/to/image.ext"/>

Một đoạn đơn giản của jQuery sao chép data-src thành src, nó sẽ bắt đầu tải hình ảnh khi bạn cần. Trong trường hợp của tôi khi trang đã tải xong.

$(document).ready(function(){
    $(".loadlater").each(function(index, element){
        $(element).attr("src", $(element).attr("data-src"));
    });
});

Tôi cá là mã jQuery có thể được viết tắt, nhưng theo cách này thì có thể hiểu được.


4
Mẹo: nếu bạn đang sử dụng data-thẻ, việc truy cập chúng dễ dàng hơn một chút $(element).data('src')thay vì$(element).attr('data-src')
Maxim Kumpan

Thật ra hôm nay tôi sẽ không sử dụng jQuery nữa. Nhưng đó là một câu hỏi về sở thích cá nhân, và phụ thuộc vào quy mô của trang web bạn đang xây dựng. Nhưng chủ đề nóng của thời đại là "Hình ảnh tiến bộ", có lẽ đó là một cái gì đó để xem xét. smashingmagazine.com/2018/02/
hy

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

Nên tốt hơn ajax vì nếu đó là thư viện và bạn đang lặp qua danh sách các bức ảnh, nếu hình ảnh đã có trong bộ đệm, nó sẽ không gửi yêu cầu khác đến máy chủ. Nó sẽ yêu cầu trong trường hợp jQuery / ajax và trả về HTTP 304 (Không được sửa đổi) và sau đó sử dụng hình ảnh gốc từ bộ đệm nếu nó đã ở đó. Phương pháp trên giảm yêu cầu trống đến máy chủ sau vòng lặp hình ảnh đầu tiên trong thư viện.


4

Bạn có thể sử dụng một đối tượng Trì hoãn để tải ASYNC.

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);
});

Vui lòng chú ý: image.onload phải ở trước image.src để ngăn sự cố với bộ đệm.


3

Nếu bạn chỉ muốn đặt nguồn của hình ảnh, bạn có thể sử dụng nguồn này.

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

3

Điều này cũng hoạt động ..

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

2

AFAIK bạn sẽ phải thực hiện một hàm .load () ở đây như được gắn với .ajax (), nhưng bạn có thể sử dụng jQuery setTimeout để duy trì hoạt động (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
xin lỗi tôi hơi hiểu nhầm Q của bạn, tôi nghĩ rằng bạn đang tải hình ảnh đang thay đổi hoặc một cái gì đó (do đó là bit ajax)
benhowdle89

2

sử dụng .load để tải hình ảnh của bạn. để kiểm tra xem bạn có gặp lỗi không (giả sử 404), bạn có thể thực hiện các bước sau:

$("#img_id").error(function(){
  //$(this).hide();
  //alert("img not loaded");
  //some action you whant here
});

cẩn thận - sự kiện .error () sẽ không kích hoạt khi thuộc tính src trống cho hình ảnh.


0

$ (hàm () {

    if ($('#hdnFromGLMS')[0].value == 'MB9262') {
        $('.clr').append('<img src="~/Images/CDAB_london.jpg">');
    }
    else
    {
        $('.clr').css("display", "none");
        $('#imgIreland').css("display", "block");
        $('.clrIrland').append('<img src="~/Images/Ireland-v1.jpg">');
    }
});

Nó hoạt động hoàn hảo, trong khi tải trang chủ, chúng tôi có thể thiết lập các hình ảnh khác nhau - từ Polaris
MadhaviLatha Bathini

Quá nhiều lộn xộn, không liên quan đến việc trả lời câu hỏi.
Maxim Kumpan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.