Charger des images de manière asynchrone avec jQuery

142

Je souhaite charger des images externes sur ma page de manière asynchrone à l'aide de jQuery et j'ai essayé ce qui suit:

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

   },
   error: function(r,x) {

   }
});

Mais cela renvoie toujours une erreur, est-il même possible de charger une image comme celle-ci?

J'ai essayé d'utiliser la .loadméthode et cela fonctionne mais je n'ai aucune idée de la façon dont je peux définir le délai d'attente si l'image n'est pas disponible (404). Comment puis-je faire ceci?

Arief
la source
Cela fonctionne pour moi: stackoverflow.com/questions/6150289/…
MrRhoads

Réponses:

199

Pas besoin d'ajax. Vous pouvez créer un nouvel élément d'image, définir son attribut source et le placer quelque part dans le document une fois le chargement terminé:

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
la source
20
que faire avec le timeout et 404?
Arief
1
comment définir le délai d'expiration avec cela? J'ai essayé cette méthode mais d'une manière ou d'une autre, la page attend toujours le chargement de l'image.
Arief
7
Si vous vérifiez la chronologie de votre navigateur, par exemple, la chronologie des outils de développement de Google Chrome, vous verrez que la création d'un élément DOM (que vous l'attachiez ou non au DOM n'a apparemment pas d'importance), puis la définition de sa source l'ajoute au chargement du document actuel. list - ainsi la page ne terminera PAS le "chargement" tant que l'élément créé ne sera pas chargé. Votre solution n'est en fait pas un événement asynchrone dans le sens où window.load () ne se déclenchera pas tant que l'image n'aura pas été chargée, différant éventuellement certaines opérations paintou layout, et certainement retardant les onloaddépendances d'événements.
Tom Auger
2
@TomAuger: Alors, comment pouvons-nous le rendre vraiment asynchrone? Je viens de tester le code avec load () et il n'est PAS asynchrone.
basZero
2
@gidzior Cela ne fonctionne pas dans IE8 car vous ne pouvez pas définir l'attribut SRC dans IE8 à l'aide de jquery. référez-vous ici: stackoverflow.com/questions/12107487/…
Rich
78

SI VOUS AVEZ VRAIMENT BESOIN D'UTILISER AJAX ...

Je suis tombé sur des cas d'utilisation où les gestionnaires de chargement n'étaient pas le bon choix. Dans mon cas lors de l'impression via javascript. Il existe donc en fait deux options pour utiliser le style AJAX pour cela:

Solution 1

Utilisez des données d'image Base64 et un service d'image REST. Si vous disposez de votre propre webservice, vous pouvez ajouter un script JSP / PHP REST qui propose des images en encodage Base64. Maintenant, comment est-ce utile? Je suis tombé sur une nouvelle syntaxe sympa pour l'encodage d'image:

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

Ainsi, vous pouvez charger les données Image Base64 à l'aide d'Ajax, puis à la fin vous créez la chaîne de données Base64 sur l'image! Très amusant :). Je recommande d'utiliser ce site http://www.freeformatter.com/base64-encoder.html pour l'encodage d'images.

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

Solution 2:

Incitez le navigateur à utiliser son cache. Cela vous donne un joli fadeIn () lorsque la ressource est dans le cache du navigateur:

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

Cependant, les deux méthodes ont leurs inconvénients: la première ne fonctionne que sur les navigateurs modernes. Le second a des problèmes de performances et repose sur l'hypothèse de l'utilisation du cache.

acclamations, volonté

mschmoock
la source
1
Si l'état actuel de la prise en charge du navigateur vous convient ( caniuse.com/#search=Blob ), vous pouvez utiliser des Blobs au lieu des URI de données. Cela `` semble '' moins piraté que l'utilisation d'URI de données encodées en base64 et représente également moins de gaspillage de mémoire (puisque base64 n'est pas un format efficace en mémoire), bien que ce dernier n'ait probablement pas d'importance la plupart du temps dans le monde réel.
Mark Amery
11

En utilisant jQuery, vous pouvez simplement changer l'attribut "src" en "data-src". L'image ne sera pas chargée. Mais l'emplacement est stocké avec l'étiquette. Que j'aime.

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

Un simple morceau de jQuery copie data-src dans src, qui commencera à charger l'image lorsque vous en aurez besoin. Dans mon cas, lorsque la page a fini de se charger.

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

Je parie que le code jQuery pourrait être abrégé, mais c'est compréhensible de cette façon.

htho
la source
4
Conseil: si vous utilisez les data-balises, il est un peu plus facile d'y accéder via $(element).data('src')au lieu de$(element).attr('data-src')
Maxim Kumpan
En fait, aujourd'hui, je n'utiliserais plus jQuery. Mais c'est une question de goût personnel, et dépend de l'échelle du site Web que vous créez. Mais le sujet brûlant de l'époque est "Progressive Images", c'est peut-être quelque chose à regarder. smashingmagazine.com/2018/02/…
htho
8
$(<img />).attr('src','http://somedomain.com/image.jpg');

Cela devrait être meilleur que ajax car si c'est une galerie et que vous parcourez une liste de photos, si l'image est déjà dans le cache, elle n'enverra pas une autre demande au serveur. Il demandera dans le cas de jQuery / ajax et retournera un HTTP 304 (non modifié), puis utilisera l'image d'origine du cache si elle est déjà là. La méthode ci-dessus réduit une demande vide au serveur après la première boucle d'images dans la galerie.

Jaseem
la source
4

Vous pouvez utiliser des objets différés pour le chargement 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);
});

Veuillez faire attention: image.onload doit être avant image.src pour éviter les problèmes de cache.

phpcoding
la source
3

Si vous souhaitez simplement définir la source de l'image, vous pouvez l'utiliser.

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

Cela fonctionne aussi.

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

AFAIK vous auriez à faire une fonction .load () ici comme apposée au .ajax (), mais vous pourriez utiliser jQuery setTimeout pour le garder en direct (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
la source
2
désolé j'ai légèrement mal compris votre Q, je pensais que vous chargiez des images qui changeaient ou quelque chose (d'où le bit ajax)
benhowdle89
2

utilisez .load pour charger votre image. pour tester si vous obtenez une erreur (disons 404), vous pouvez faire ce qui suit:

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

attention - l'événement .error () ne se déclenchera pas lorsque l'attribut src est vide pour une image.

Poelinca Dorin
la source
0

$ (fonction () {

    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
la source
Cela fonctionne parfaitement
Trop de désordre, sans rapport avec la réponse à la question.
Maxim Kumpan