2010-06-10 12 views
47

Después de que un usuario cargue un archivo, tenemos que hacer un procesamiento adicional con las imágenes, como cambiar el tamaño y subirlo a S3. Esto puede tomar hasta 10 segundos adicionales. Obviamente hacemos esto en un segundo plano. Sin embargo, queremos mostrarle al usuario la página de resultados inmediatamente y simplemente mostrar los rotadores en su lugar hasta que las imágenes lleguen a su hogar permanente en s3.Detectando una imagen 404 en javascript

Estoy buscando una forma de detectar que una determinada imagen no se cargó correctamente (404) de forma cruzada. Si eso sucede, queremos utilizar JS para mostrar un spinner en su lugar y volver a cargar la imagen cada pocos segundos hasta que se pueda cargar correctamente desde s3.

+1

IIRC, hay un evento onerror para imágenes ... http://www.devguru.com/technologies/javascript/10916.asp – scunliffe

+2

Ver http://stackoverflow.com/questions/92720/jquery-javascript -to-replace-broken-images –

Respuesta

8

Desde: http://lucassmith.name/2008/11/is-my-image-loaded.html

// First a couple helper functions 
function $(id) { 
    return !id || id.nodeType === 1 ? id : document.getElementById(id); 
} 
function isType(o,t) { return (typeof o).indexOf(t.charAt(0).toLowerCase()) === 0;} 

// Here's the meat and potatoes 
function image(src,cfg) { var img, prop, target; 
    cfg = cfg || (isType(src,'o') ? src : {}); 

    img = $(src); 
    if (img) { 
     src = cfg.src || img.src; 
    } else { 
     img = document.createElement('img'); 
     src = src || cfg.src; 
    } 

    if (!src) { 
     return null; 
    } 

    prop = isType(img.naturalWidth,'u') ? 'width' : 'naturalWidth'; 
    img.alt = cfg.alt || img.alt; 

    // Add the image and insert if requested (must be on DOM to load or 
    // pull from cache) 
    img.src = src; 

    target = $(cfg.target); 
    if (target) { 
     target.insertBefore(img, $(cfg.insertBefore) || null); 
    } 

    // Loaded? 
    if (img.complete) { 
     if (img[prop]) { 
      if (isType(cfg.success,'f')) { 
       cfg.success.call(img); 
      } 
     } else { 
      if (isType(cfg.failure,'f')) { 
       cfg.failure.call(img); 
      } 
     } 
    } else { 
     if (isType(cfg.success,'f')) { 
      img.onload = cfg.success; 
     } 
     if (isType(cfg.failure,'f')) { 
      img.onerror = cfg.failure; 
     } 
    } 

    return img; 
} 

Y aquí cómo usarlo:

image('imgId',{ 
    success : function() { alert(this.width); }, 
    failure : function() { alert('Damn your eyes!'); }, 
}); 

image('http://somedomain.com/image/typooed_url.jpg', { 
    success : function() {...}, 
    failure : function() {...}, 
    target : 'myContainerId', 
    insertBefore : 'someChildOfmyContainerId' 
}); 
+0

Esto plantea un buen punto.Usted (OP) necesita cargar las imágenes con parámetros aleatorios de cadena de consulta. – SLaks

+6

El enlace murió. Esta respuesta debe enmendarse para que contenga el contenido o se le quita su tilde verde. – mxcl

+0

KISS (también conocido como Keep It Super Simple) –

49

Maneje el evento <img> del elemento onerror.

+9

@xal: Solo asegúrate de enganchar el evento 'error' antes de * establecer la propiedad' src' (si estás haciendo esto con 'new Image' o' document.createElement ("img") 'en lugar de a través de una cadena HTML). De lo contrario, estás en una condición de carrera y el evento podría disparar antes de comenzar a manejarlo (al igual que el evento 'carga'). –

+1

@ T.J: No necesariamente. Javascript se ejecuta en el hilo de la interfaz de usuario, por lo que si maneja el evento inmediatamente después de configurar 'src', no debería haber ningún riesgo. Sin embargo, aún tiene razón, – SLaks

+7

Javascript se ejecuta en el hilo de Javascript, que en * algunos navegadores * es también el hilo de la interfaz de usuario. No es necesariamente el hilo de descarga. He ayudado a las personas a corregir errores causados ​​precisamente por esto, estableciendo 'src' antes de configurar un controlador' load'. Hay una condición de carrera allí. Si ya tiene registrado el controlador, el código de manejo del evento lo colocará en la pila de ejecución para que se ejecute una vez que el hilo JS esté disponible para hacer otra cosa. Si no lo haces, puedes perderte el evento. –

0

Esto funcionó para mí (el mío está en CoffeeScript). Deberás reemplazarlo con un girador, por supuesto.

checkImages = -> 
    $("img").each -> 
    $(this).error -> 
     $(this).attr("src", "../default/image.jpg") 

$(document).on('page:load', checkImages) 

estoy adivinando el equivalente JavaScript es algo así como

function checkImages() { 
    $("img").each(function() { 
    $(this).error(function() { 
     $(this).attr("src", "../default/image.jpg"); 
    }); 
    }); 
}; 

$ (document) .en ("página: carga", checkImages);

9

solo enlaza el disparador attr en el evento de error.

$(myimgvar).bind('error',function(ev){ 
    //error has been thrown 
    $(this).attr('src','/path/to/no-artwork-available.jpg'); 
}).attr('src',urlvar); 
+1

Esto supone que todas las cargas fallidas son 404. – Bangkokian

7

Primera opción:

<img src="picture1.gif" onerror="this.onerror=null;this.src='missing.gif';"/> 

Segunda opción:

<html> 
<head> 
<script type="text/javascript"> 
    function ImgError(source){ 
     source.src = "/noimage.gif"; 
     source.onerror = ""; 
     return true; 
    } 
</script> 
</head> 
<body> 
    <img src="image_example1.jpg" onerror="ImgError(this)" /> 
</body> 
</html> 

Ejemplo en Fidler

https://jsfiddle.net/dorathoto/8z4Ltzp8/

Cuestiones relacionadas