Asynchronicznie ładuj obrazy za pomocą jQuery

142

Chcę ładować obrazy zewnętrzne na mojej stronie asynchronicznie za pomocą jQuery i wypróbowałem następujące rozwiązania:

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

   },
   error: function(r,x) {

   }
});

Ale zawsze zwraca błąd, czy w ogóle można załadować taki obraz?

Próbowałem użyć .loadmetody i działa, ale nie mam pojęcia, jak ustawić limit czasu, jeśli obraz nie jest dostępny (404). W jaki sposób mogę to zrobić?

Arief
źródło
To działa dla mnie: stackoverflow.com/questions/6150289/…
MrRhoads

Odpowiedzi:

199

Nie ma potrzeby Ajax. Możesz utworzyć nowy element obrazu, ustawić jego atrybut źródłowy i umieścić go gdzieś w dokumencie po zakończeniu ładowania:

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);
        }
    });
karim79
źródło
20
co zrobić z limitem czasu i 404?
Arief
1
jak ustawić z tym limit czasu? Wypróbowałem tę metodę, ale jakoś strona nadal czeka na załadowanie obrazu.
Arief
7
Jeśli sprawdzisz oś czasu swojej przeglądarki, na przykład oś czasu narzędzi programistycznych Google Chrome, zobaczysz, że utworzenie dowolnego elementu DOM (bez względu na to, czy dołączysz go do DOM, jest najwyraźniej nieistotne), a następnie ustawienie jego źródła powoduje dodanie go do ładowania bieżącego dokumentu list - tak więc strona NIE zakończy się "ładowaniem", dopóki utworzony element nie zostanie załadowany. Twoje rozwiązanie w rzeczywistości nie jest zdarzeniem asynchronicznym w tym sensie, że window.load () nie zostanie uruchomione, dopóki obraz nie zostanie załadowany, prawdopodobnie odraczając pewne operacje paintlub z layoutpewnością opóźniając wszelkie onloadzależności zdarzeń.
Tom Auger
2
@TomAuger: Jak więc możemy sprawić, by był naprawdę asynchroniczny? Właśnie przetestowałem kod za pomocą load () i NIE jest on asynchroniczny.
basZero
2
@gidzior To nie działa w IE8, ponieważ nie można ustawić atrybutu SRC w IE8 za pomocą jquery. zobacz tutaj: stackoverflow.com/questions/12107487/…
Rich
78

JEŚLI NAPRAWDĘ POTRZEBUJESZ UŻYWAĆ AJAX ...

Spotkałem się z przypadkami, w których obsługa załadunku nie była właściwym wyborem. W moim przypadku podczas drukowania za pomocą javascript. W rzeczywistości istnieją dwie opcje użycia stylu AJAX do tego:

Rozwiązanie 1

Użyj danych obrazu Base64 i usługi obrazu REST. Jeśli masz własną usługę internetową, możesz dodać skrypt JSP / PHP REST, który oferuje obrazy w kodowaniu Base64. Jak to jest przydatne? Natknąłem się na nową, fajną składnię do kodowania obrazu:

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

Możesz więc załadować dane obrazu Base64 za pomocą Ajax, a następnie po zakończeniu zbudować ciąg danych Base64 do obrazu! Świetna zabawa :). Polecam skorzystać z tej witryny http://www.freeformatter.com/base64-encoder.html do kodowania obrazu.

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

Rozwiązanie 2:

Oszukaj przeglądarkę, aby użyła jej pamięci podręcznej. Daje to przyjemną funkcję fadeIn (), gdy zasób znajduje się w pamięci podręcznej przeglądarki:

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

Jednak obie metody mają swoje wady: pierwsza działa tylko w nowoczesnych przeglądarkach. Drugi ma problemy z wydajnością i opiera się na założeniu, w jaki sposób będzie używana pamięć podręczna.

okrzyki, will

mschmoock
źródło
1
Jeśli aktualny stan obsługi przeglądarki jest dla Ciebie akceptowalny ( caniuse.com/#search=Blob ), możesz użyć obiektów BLOB zamiast identyfikatorów URI danych. To `` wydaje się '' mniej hakerskie niż używanie identyfikatorów URI danych zakodowanych w base64, a także mniej marnuje pamięć (ponieważ base64 nie jest formatem wydajnym pod kątem pamięci), chociaż ten ostatni prawdopodobnie nie ma znaczenia w prawdziwym świecie.
Mark Amery,
11

Używając jQuery możesz po prostu zmienić atrybut „src” na „data-src”. Obraz nie zostanie załadowany. Ale lokalizacja jest przechowywana ze znacznikiem. Które lubię.

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

Prosty fragment jQuery kopiuje data-src do src, który rozpocznie ładowanie obrazu, gdy będzie potrzebny. W moim przypadku, gdy strona się załadowała.

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

Założę się, że kod jQuery można by skrócić, ale w ten sposób jest to zrozumiałe.

htho
źródło
4
Wskazówka: jeśli używasz data-tagów, dostęp do nich jest nieco łatwiejszy przez $(element).data('src')zamiast$(element).attr('data-src')
Maxim Kumpan
Właściwie dzisiaj nie użyłbym już jQuery. Ale to kwestia osobistego gustu i zależy od skali witryny, którą budujesz. Ale gorącym tematem tamtych czasów są „obrazy progresywne”, być może warto się temu przyjrzeć. smashingmagazine.com/2018/02/…
htho
8
$(<img />).attr('src','http://somedomain.com/image.jpg');

Powinno być lepsze niż Ajax, ponieważ jeśli jest to galeria i przeglądasz listę zdjęć, jeśli obraz jest już w pamięci podręcznej, nie wyśle ​​kolejnego żądania do serwera. Będzie zażądać w przypadku jQuery / ajax i zwróci HTTP 304 (niezmodyfikowany), a następnie użyje oryginalnego obrazu z pamięci podręcznej, jeśli już tam jest. Powyższa metoda redukuje puste żądanie do serwera po pierwszej pętli obrazów w galerii.

Jaseem
źródło
4

Możesz użyć obiektów odroczonych do ładowania 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);
});

Zwróć uwagę: image.onload musi znajdować się przed image.src, aby uniknąć problemów z cache.

phpcoding
źródło
3

Jeśli chcesz tylko ustawić źródło obrazu, możesz tego użyć.

$("img").attr('src','http://somedomain.com/image.jpg');
slobodan
źródło
3

To też działa ...

var image = new Image();
image.src = 'image url';
image.onload = function(e){
  // functionalities on load
}
$("#img-container").append(image);
Basilin Joe
źródło
2

AFAIK, musiałbyś tutaj wykonać funkcję .load () jako dołączoną do .ajax (), ale możesz użyć jQuery setTimeout, aby utrzymać ją na żywo (ish)

<script>
 $(document).ready(function() {
 $.ajaxSetup({
    cache: false
});
 $("#placeholder").load("PATH TO IMAGE");
   var refreshId = setInterval(function() {
      $("#placeholder").load("PATH TO IMAGE");
   }, 500);
});
</script>
benhowdle89
źródło
2
przepraszam, trochę źle zrozumiałem twój Q, myślałem, że ładujesz obrazy, które się zmieniają lub coś takiego (stąd bit
Ajax
2

użyj .load, aby załadować obraz. aby sprawdzić, czy pojawia się błąd (powiedzmy 404), możesz wykonać następujące czynności:

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

uwaga - zdarzenie .error () nie zostanie wywołane, gdy atrybut src jest pusty dla obrazu.

Poelinca Dorin
źródło
0

$ (funkcja () {

    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">');
    }
});
MadhaviLatha Bathini
źródło
Działa idealnie
Za dużo bałaganu, niezwiązanego z odpowiedzią na pytanie.
Maxim Kumpan