Cargar imágenes asincrónicamente con jQuery

142

Quiero cargar imágenes externas en mi página de forma asíncrona usando jQuery y he intentado lo siguiente:

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

   },
   error: function(r,x) {

   }
});

Pero siempre devuelve un error, ¿es posible cargar una imagen como esta?

Traté de usar el .loadmétodo y funciona, pero no tengo idea de cómo puedo configurar el tiempo de espera si la imagen no está disponible (404). ¿Cómo puedo hacer esto?

Pena
fuente
Esto funciona para mí: stackoverflow.com/questions/6150289/…
MrRhoads

Respuestas:

199

No hay necesidad de ajax. Puede crear un nuevo elemento de imagen, establecer su atributo de origen y colocarlo en algún lugar del documento una vez que haya terminado de cargarse:

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
fuente
20
¿Qué hacer con el tiempo de espera y 404?
Arief
1
¿Cómo configurar el tiempo de espera con esto? Intenté este método pero de alguna manera la página todavía espera a que se cargue la imagen.
Arief
77
Si verifica la línea de tiempo de su navegador, por ejemplo, la línea de tiempo de las herramientas de desarrollo de Google Chrome, verá que crear cualquier elemento DOM (independientemente de si lo adjunta o no al DOM es aparentemente irrelevante) y luego establecer su fuente lo agrega a la carga del documento actual lista: para que la página NO termine de "cargarse" hasta que se cargue el elemento creado. Su solución en realidad no es un evento asíncrono en el sentido de que window.load () no se disparará hasta que la imagen se haya cargado, posiblemente diferiendo ciertas operaciones paintu layoutoperaciones, y ciertamente retrasando cualquier onloaddependencia de eventos.
Tom Auger
2
@TomAuger: Entonces, ¿cómo podemos hacer que sea realmente asíncrono? Acabo de probar el código con load () y NO es asíncrono.
basZero
2
@gidzior No funciona en IE8 porque no puede establecer el atributo SRC en IE8 usando jquery. consulte aquí: stackoverflow.com/questions/12107487/…
Rich
78

SI REALMENTE NECESITA USAR AJAX ...

Encontré casos de uso donde los manipuladores de carga no eran la elección correcta. En mi caso cuando imprimo vía javascript. Entonces, en realidad, hay dos opciones para usar el estilo AJAX para esto:

Solución 1

Utilice datos de imagen Base64 y un servicio de imagen REST. Si tiene su propio servicio web, puede agregar un script JSP / PHP REST que ofrezca imágenes en codificación Base64. Ahora, ¿cómo es eso útil? Encontré una sintaxis nueva y genial para la codificación de imágenes:

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

Por lo tanto, puede cargar los datos de la imagen Base64 usando Ajax y luego, al finalizar, construye la cadena de datos Base64 en la imagen. Gran diversión :). Recomiendo usar este sitio http://www.freeformatter.com/base64-encoder.html para la codificación de imágenes.

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

Solución2:

Engaña al navegador para usar su caché. Esto le da un buen fadeIn () cuando el recurso está en la memoria caché del navegador:

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

Sin embargo, ambos métodos tienen sus inconvenientes: el primero solo funciona en los navegadores modernos. El segundo tiene fallas de rendimiento y se basa en la suposición de cómo se usará el caché.

aplausos

mschmoock
fuente
1
Si el estado actual de soporte del navegador es aceptable para usted ( caniuse.com/#search=Blob ), puede usar Blobs en lugar de URI de datos. Esto 'se siente' menos hacky que usar URI de datos codificados en base64 y también es menos derrochador de memoria (ya que base64 no es un formato eficiente en memoria), aunque este último probablemente no importe la mayor parte del tiempo en el mundo real.
Mark Amery
11

Con jQuery, simplemente puede cambiar el atributo "src" a "data-src". La imagen no se cargará. Pero la ubicación se almacena con la etiqueta. Que me gusta

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

Una pieza simple de jQuery copia data-src a src, que comenzará a cargar la imagen cuando la necesite. En mi caso cuando la página ha terminado de cargarse.

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

Apuesto a que el código jQuery podría abreviarse, pero es comprensible de esta manera.

htho
fuente
44
Consejo: si estás usando las data-etiquetas, es una feria poco más fácil el acceso a ellos a través de $(element).data('src')lugar de$(element).attr('data-src')
Maxim Kumpan
En realidad hoy ya no usaría jQuery. Pero esa es una cuestión de gusto personal, y depende de la escala del sitio web que está creando. Pero el tema candente de la época es "Imágenes progresivas", tal vez es algo a lo que hay que prestarle atención. smashingmagazine.com/2018/02/…
htho
8
$(<img />).attr('src','http://somedomain.com/image.jpg');

Debería ser mejor que ajax porque si es una galería y estás recorriendo una lista de fotos, si la imagen ya está en caché, no enviará otra solicitud al servidor. Solicitará en el caso de jQuery / ajax y devolverá un HTTP 304 (No modificado) y luego usará la imagen original del caché si ya está allí. El método anterior reduce una solicitud vacía al servidor después del primer bucle de imágenes en la galería.

Jaseem
fuente
4

Puede utilizar objetos diferidos para cargar 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);
});

Por favor, preste atención: image.onload debe estar antes de image.src para evitar problemas con el caché.

phpcoding
fuente
3

Si solo desea establecer la fuente de la imagen, puede usar esto.

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

Esto también funciona ...

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

AFAIK tendrías que hacer una función .load () aquí como se aplica a .ajax (), pero puedes usar jQuery setTimeout para mantenerlo activo (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
fuente
2
lo siento no he entendido bien ligeramente su Q, pensé que eras la carga de imágenes que cambiaban o algo (de ahí el bit Ajax)
benhowdle89
2

use .load para cargar su imagen. para probar si obtiene un error (digamos 404) puede hacer lo siguiente:

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

cuidado: el evento .error () no se activará cuando el atributo src esté vacío para una imagen.

Poelinca Dorin
fuente
0

$ (function () {

    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
fuente
Funciona
Demasiado desorden, sin relación con la respuesta a la pregunta.
Maxim Kumpan