2012-03-22 11 views
54

Czy istnieje sposób na sprawdzenie, czy ścieżka obrazu prowadzi do rzeczywistego obrazu, tj. Wykrywanie, kiedy obraz nie jest ładowany w JavaScript.Wykrywanie, kiedy obraz nie może się załadować w JavaScript

Dla aplikacji internetowej parsuję plik xml i dynamicznie tworzę obrazy HTML z listy ścieżek obrazów. Niektóre ścieżki obrazu mogą już nie istnieć na serwerze, więc chcę z powodzeniem zakończyć się niepowodzeniem, wykrywając, które obrazy się nie ładują i usuwając element HTML img.

Uwaga: Rozwiązania JQuery nie będą mogły być używane (szef nie chce używać JQuery, tak, wiem, nie zaczynaj mnie). Znam sposób w JQuery, aby wykryć, kiedy obraz jest załadowany, ale nie, czy się nie udało.

Mój kod do tworzenia elementów IMG, ale jak wykryć, czy ścieżka img prowadzi do nieudanego załadowania obrazu?

+0

To może pomóc: http://stackoverflow.com/questions/1977871/check-if-an-image-is-loaded-no-errors -in-javascript (to jQuery, ale nadal może prowadzić cię na właściwą ścieżkę) –

+0

wypróbuj jeden z poniższych https://www.google.com/search?rlz=1C1CHJL_esMX444MX444&sourceid=chrome&ie=UTF-8&q=Detect+when+ an + obraz + zawiedzie + do + obciążenia + w + Javascript # hl = en & rlz = 1C1CHJL_esMX444MX444 & sclient = psy-ab & q = witryna% 3Ahttp% 3A% 2F% 2Fstackoverflow.com + Wykryj + gdy + an + obraz + nie powiedzie się + aby + załadować + w + Javascript & oq = site: http% 3A% 2F% 2Fstackoverflow.com + Wykryj + gdy + obraz + obraz + nie powiedzie się + do + załaduj + w + Javascript i aq = f & aqi = & aql = & gs_l = serp.12 ...4485l10141l0l11322l11l9l0l0l0l0l165l703l8j1l9l0.frgbld. & PBX = 1 & bav = on.2, or.r_gc.r_pw.r_qf., Cf.osb & fp = 19d0ebe5924d5495 & BIW = 1024 & bih = 653 – ajax333221

+1

Funny @ ajax333221 to samo pytanie jest pierwszym w wynikach linku :) –

Odpowiedz

63

Możesz spróbować następującego kodu. Nie mogę jednak ręczyć za zgodność przeglądarki, więc musisz to przetestować.

function testImage(URL) { 
    var tester=new Image(); 
    tester.onload=imageFound; 
    tester.onerror=imageNotFound; 
    tester.src=URL; 
} 

function imageFound() { 
    alert('That image is found and loaded'); 
} 

function imageNotFound() { 
    alert('That image was not found.'); 
} 

testImage("http://foo.com/bar.jpg"); 

I moje sympatie dla szefa odpornego na jQuery!

+1

jakiś pomysł czy istnieje sposób na stwierdzenie, czy napotka przekierowanie? – quickshiftin

+2

To nie działa w webKit (Epiphany, Safari, ...) w zależności od serwera, z którego otrzymujesz obraz. Na przykład, czasami imgur nie wysyła obrazu, który istnieje, ani statusu 404, a zdarzenie błędu nie jest w tym przypadku wywoływane. –

3

Oto funkcja, którą napisałem dla innej odpowiedzi: Javascript Image Url Verify. Nie wiem, czy jest to dokładnie to, czego potrzebujesz, ale używa różnych technik, których używałbyś, obejmujących procedury obsługi dla onload, onerror, i ogólnego limitu czasu.

Ponieważ ładowanie obrazu jest asynchroniczne, wywołuje się tę funkcję wraz z obrazem, a następnie wywołuje ona połączenie zwrotne w późniejszym czasie z wynikiem.

-14

tak jak poniżej:

var img = new Image(); 
img.src = imgUrl; 

if (!img.complete) { 

//has picture 
} 
else //not{ 

} 
+3

Nie. Może to pomóc w określeniu, czy obraz jest buforowany, w niektórych przeglądarkach - ale bez wywołania zwrotnego obciążenia, nie czekasz nawet przez chwilę, aby dać przeglądarce szansę zainicjowania żądania HTTP dla tego obrazu. – ChaseMoskal

+0

to tylko coś do powiedzenia! – Hitmands

+2

Ładowanie obrazu jest asynchroniczne. –

19

Odpowiedź jest ładny, ale wprowadza jeden problem. Za każdym razem, gdy bezpośrednio przypisujesz onload lub onerror, może on zastąpić wywołanie zwrotne, które zostało wcześniej przypisane. Dlatego istnieje niezła metoda, która "rejestruje określonego detektora w EventTarget, który jest wywoływany na", jak mówią na MDN. Możesz zarejestrować tylu słuchaczy, ile chcesz na tym samym wydarzeniu.

Pozwól, że trochę poprawię odpowiedź.

function testImage(url) { 
    var tester = new Image(); 
    tester.addEventListener('load', imageFound); 
    tester.addEventListener('error', imageNotFound); 
    tester.src = url; 
} 

function imageFound() { 
    alert('That image is found and loaded'); 
} 

function imageNotFound() { 
    alert('That image was not found.'); 
} 

testImage("http://foo.com/bar.jpg"); 

Ponieważ zewnętrzny proces ładowania zasobów jest asynchroniczny, byłoby jeszcze ładniejszy w użyciu nowoczesnego JavaScript obietnicami, jak poniżej.

function testImage(url) { 

    // Define the promise 
    const imgPromise = new Promise(function imgPromise(resolve, reject) { 

     // Create the image 
     const imgElement = new Image(); 

     // When image is loaded, resolve the promise 
     imgElement.addEventListener('load', function imgOnLoad() { 
      resolve(this); 
     }); 

     // When there's an error during load, reject the promise 
     imgElement.addEventListener('error', function imgOnError() { 
      reject(); 
     }) 

     // Assign URL 
     imgElement.src = url; 

    }); 

    return imgPromise; 
} 

testImage("http://foo.com/bar.jpg").then(

    function fulfilled(img) { 
     console.log('That image is found and loaded', img); 
    }, 

    function rejected() { 
     console.log('That image was not found'); 
    } 

); 
+0

może brakuje mi czegoś, ale w jaki sposób przypisanie (tester.onload = ..) może zastąpić wywołanie zwrotne, jeśli właśnie utworzono "tester"? nawet jeśli jakiś niejasny fragment kodu dodaje zdarzenie do każdego tworzonego obrazu, nie jest oczywiste, że chcemy zachować te zdarzenia w celu wykrycia, czy obraz istnieje. – jvilhena

+0

Masz całkowitą rację. W tym konkretnym przypadku nie stanowi to problemu, ponieważ jest wysoce prawdopodobne, że nie zostanie zastąpiony. Ogólnie jednak dodanie detektora zdarzeń jest lepszą praktyką niż bezpośrednie przypisywanie metody. –

+0

Nowoczesny JavaScript bez funkcji strzałek i asynchronizacji/czekania? :) –

2
/** 
* Tests image load. 
* @param {String} url 
* @returns {Promise} 
*/ 
function testImageUrl(url) { 
    return new Promise(function(resolve, reject) { 
    var image = new Image(); 
    image.addEventListener('load', resolve); 
    image.addEventListener('error', reject); 
    image.src = url; 
    }); 
} 

return testImageUrl(imageUrl).then(function imageLoaded(e) { 
    return imageUrl; 
}) 
.catch(function imageFailed(e) { 
    return defaultImageUrl; 
}); 
0

to:

<img onerror="this.src='/images/image.png'" src="..."> 
+1

Chociaż jest to przydatny atrybut, który może być użyty jako technika przełączania obrazu, bardziej zrozumiała odpowiedź byłaby pomocna dla czytelników, aby to zrozumieć. – sorak

Powiązane problemy