[js] Przerwanie wykonywanej akcji w objekcie Image

0

Heja

Mam taki kod:

var img=new Image();
img.src='http://adres.obrazka.pl';

I teraz chciałbym aby w przypadku gdy obrazek jest b. duży (tj. wczytuje się zbyt długo) akcja została przerwana.

Próbowalem

var przerwa=setTimeout(function(){img=null},70000);

ale mimo to po tym upływie czasu obrazek nadal ładuje się w przeglądarce.

Prosiłbym o jakąś małą pomoc :)

0

Jeśli wstrzykujesz zmienną img do DOM, to jej ustawienie na null nie ma żadnego znaczenia. Sam pomysł z wykorzystaniem setTimeout jest dobry.

Proponuję, byś po upływie czasu granicznego ustawił atrybut src obrazka na wartość pustą, a następnie usunął go z DOM (jeśli tam się znajduje) i dopiero potem ustawił wszystkie referencje do obrazka na null.

To powinno zadziałać, ale niestety -- z uwagi na niedoskonałości przeglądarek -- czasami nie działa. Nieraz pomaga ustawienie atrybutu src na wartość inną niż pusta (na URL małego lub nieistniejącego obrazka).

Niestety, sytuacja nie jest zbyt różowa i może się okazać, że niewiele możesz tu zrobić. Teoretycznie, jeśli nie istniałyby żadne odniesienia do obrazka (czy to w DOM, czy to w samym JavaScripcie) , przeglądarkowy odśmiecacz mógłby anulować ładowanie obrazka. Ale z jakichś powodów to się czasem (często? zawsze?) nie dzieje.

Jeśli chcesz anulować jedyny obrazek na stronie, możesz użyć funkcji zatrzymującej ładowanie całej strony.

0

Dziękuję za odpowiedź.

Proponuję, byś po upływie czasu granicznego ustawił atrybut src obrazka na wartość pustą, a następnie usunął go z DOM (jeśli tam się znajduje) i dopiero potem ustawił wszystkie referencje do obrazka na null.

W jaki sposób mogę ustawić src na wartość pustą? Chodzi o 'null' ?

możesz użyć funkcji zatrzymującej ładowanie całej strony.

A cóż to za funkcja? Prosze wybacz moją ignorancję, ale naprawdę o niej nie słyszałem :/

0
Social_Killer napisał(a)

W jaki sposób mogę ustawić src na wartość pustą? Chodzi o 'null' ?

W src siedzi string, więc wartość pusta to... pusty string, czyli ''.

Social_Killer napisał(a)

A cóż to za funkcja? Prosze wybacz moją ignorancję, ale naprawdę o niej nie słyszałem :/

Twoja ignorancja polega jedynie na nie użyciu Google :P.

Robi się to na jeden z dwóch sposobów, zależnie od przeglądarki. Jeśli istnieje funkcja window.stop, wywołaj ją bez żadnych argumentów. W przeciwnym wypadku, jeśli istnieje funkcja document.execCommand, wywołaj ją, przekazując jej jeden parametr: łańcuch znaków 'stop'.

To spowoduje, że strona przestanie się ładować (wszystkie obrazki na stronie też).

0

Zastosowałem się do Twojej pierwszej instrukcji. I tu dziwna sprawa - jeśli po ustawieniu wartości src na pustą wstawię alerta z informacją wszystko jest ok, a kiedy ten sam tekst wypiszę za pomoca document.write strona ładuje się nadal i nadal, nie bacząc na setTimeOut.

Hm, a teraz na próbę usunąłem instrukcję o ustawianiu wartości na pustą i... nic się nie zmieniło. Nadal po alercie działa, a po document.wricie już nie. Jak to możliwe?

0

Generalnie nie powinieneś używać document.write. Ta funkcja nigdy nie powinna istnieć -- sam fakt, że może istnieć spowalnia ładowanie stron (przeglądarka, natrafiając na znacznik <script>, musi ściągnąć i uruchomić skrypt zanim przejdzie do dalszych elementów, bo skrypt może się odwoływać do document.write i może w tym miejscu chcieć coś "wypisać").

Social_Killer napisał(a)

Hm, a teraz na próbę usunąłem instrukcję o ustawianiu wartości na pustą i... nic się nie zmieniło. Nadal po alercie działa, a po document.wricie już nie. Jak to możliwe?

Wywaliłeś to ustawienie src... i nie masz tam żadnej innej instrukcji anulującej? Np. usuwanie z DOM, ustawianie odniesień do zmiennej img na null czy coś w tym stylu?

Jeśli zostały Ci tam jakieś instrukcje i obiektu img nie ma w DOM, to być może alert powoduje w Twojej przeglądarce odpalenie odśmiecacza.

Sprawa jest, jak widzisz, dosyć wątła. Nie mam teraz czasu żeby nad nią posiedzieć i wymyślić jakieś obejścia dla każdej przeglądarki -- a sam nigdy nie musiałem takiego anulowania wczytywania robić.

0

OK, mam jeszcze jedno pytanie. W pewnych przypadkach skrypt musi obsłuzyć nie jeden a kilka obrazków. Tak więc wkładając moją instrukcję do pętli for chciałbym umieścic w niej settimeouta, jednakże nie bardzo wiem jak miałaby wyglądac instrukcja przerywająca.

Chodzi o coś w stylu:
setTimeout(function(){break;},70000);
wewnątrz pętli.

Podane rozwiązanie jest wg mojego IDE błędne.

0

@Social_Killer:
Instrukcja for rozciąga się tylko na funkcję, w której jest zadeklarowana. W pierwszym argumencie setTimeout masz kolejną funkcję -- anonimową. Nie może tam być break, bo w tej funkcji nie ma instrukcji for. Instrukcja for jest w funkcji zewnętrznej.

Możesz zrobić coś takiego (wydzielenie funkcji dodającej jeden obrazek jest niezbędne; pisałem to z palca więc mogą być literówki):

var IMAGE_SRC_ARRAY = ['foo.jpg', 'bar.jpg', 'baz.jpg'],
    IMAGE_TIMEOUT = 7000;

function loadAllImages(srcArray) {
  for (var i = 0; i < srcArray.length; i++) {
    loadImage(srcArray[i]);
  }
}

function loadImage(src) {
  var img = new Image();
  img.src = src;
  setTimeout(abortThisImage, IMAGE_TIMEOUT);

  function abortThisImage() { // wydzieliłem tę funkcję dla czytelności
    img.src = '';
    // (ew. usuń img z DOM)
    img = null;
    // (ew. zrób to window.stop)
  }
}

// i wywołanie:
loadAllImages(IMAGE_SRC_ARRAY);

Zauważ, że -- zależnie od tego co chcesz zrobić -- konieczna może być jedna rzecz. "Wyłączenie timeoutu" gdy obrazek zostanie załadowany. W takim wypadku możesz nie chcieć zmieniać jego src. A teraz to anulujemy ładowanie zawsze gdy minie 7 sekund, niezależnie od tego, czy obrazek się załaduje, czy nie.

Można to zrobić np. tak:

function loadImage(src) {
  var img = new Image(),
      abortTimeoutId = setTimeout(abortThisImage, IMAGE_TIMEOUT);
  img.src = src;
  img.onload = clearAbortTimeout;

  function abortThisImage() {
    // ...
  }

  function clearAbortTimeout() { // również -- wydzielona dla czytelności
    clearTimeout(abortTimeoutId);
  }
}
0

Sporo się napisałeś, dziękuję.

Co do clearTimeouta, tak wiem o tym, ale wstawiałem tutaj zeby nie zaciemniać kodu.

Jak na razie wszystko działa z takim wyjątkiem że niektóre duże obrazki poprawnie są przerywane po 70 sekundach natomiast inne (jakieś 1% testowanych) pobiera się dalej nie zważając na nic.

0

Aha i jeszcze zapomniałem napisać. Twój kod jest ok, ale niestety nie pasuje do struktury mojej aplikacji. Czy znasz może jakiś sposób na "continue" w pętli za pomocą setTimeOut?

0

Wklej tę pętlę, choćby jej schemat. Ciężko mi się domyślić w czym jest problem. Nie da się zrobić tego continue i break wewnątrz funkcji wywołania zwrotnego, przekazywanej do setTimeout.

Myślę, że tak czy siak da to się przerobić, żeby działało. Zawsze można np. wydzielić metodę, czy coś.

0

Źle się wyraziłem. Pętle zrobiłem na wzór który podałeś, tak by pasowała do mojego skryptu, jednak
niektóre duże obrazki poprawnie są przerywane po 70 sekundach natomiast inne (jakieś 1% testowanych) pobiera się dalej nie zważając na nic.

BTW mówisz wiele o DOM, a jedyne co znalazłem to nic nie znaczące wzmanki na webmade, wikibooks itp. Co rozumiesz przez dodanie/usuniecie zmiennej z DOM?

I czy da się zrobić tak, żeby cały proces odbywał się w tle, bez ciągłego ładowania się strony?

0

Twoja pętla działa synchronicznie, - nie zatrzymasz jej przez setTimeout (przynajmniej nie w twoim przypadku). To znaczy: praktycznie cała pętla się wykonuje zanim zdołasz osądzić czy powinieneś ją przerwać lub nie na podstawie tego jaki obrazek się wczytuje do img.

0

OK, myślę, że sobie poradziłem - w pętli informacje zapisywane są do zewnętrznej zmiennej. Jednak aby to sprawdzić muszę odczytać tą zmienną kiedy wszystkie timeouty zostaną wykonane. Da się jakoś ustawić setTimeOut by wykonało się wtedy kiedy wszystkie inne już się skończą?

I ponawiam drugie pytanie czy da się zrobić tak, żeby cały proces odbywał się w tle, bez ciągłego ładowania się strony?

0

OK, udało mi się zażegnać wszystkie problemy, ale pojawił się inny. Jest związany z tym więc nie będę zakładał nowego tematu.

A więc - w zależności od rangi użytkownika ma on dostęp do określonej części obrazów. Tak więc niektóre z nich podczas próby pobrania mogą żądać zalogowania poprzez htpassword. Chciałbym aby JS to wykrył i przeszedł do nastepnego obrazka pomijając ten niedostepny. W chwili obecnej jest tak że użytkownikowi wyświetla się okienko z logowaniem przez htpassword, a moim celem jest by go w ogóle nie zobaczył.

1 użytkowników online, w tym zalogowanych: 0, gości: 1