2013-06-25 40 views
168

Używam AngularJS od jakiegoś czasu i znalazłem potrzebę używania $timeout co jakiś czas (Wydaje się, że zazwyczaj należy zainicjować wtyczkę jQuery).

Niedawno próbowałem uzyskać lepsze i bardziej dogłębne zrozumienie cyklu trawienia, a ja natknąłem się na funkcję $evalAsync.

Wygląda na to, że funkcja daje podobne wyniki do $timeout, tylko nie zwlekaj. Za każdym razem, gdy używałem $timeout, było to z opóźnieniem wynoszącym 0, więc teraz zastanawiam się, czy powinienem był zamiast tego użyć $evalAsync.

Czy są jakieś zasadnicze różnice między tymi dwoma? W jakich przypadkach używałbyś jednego z drugim? Chciałbym mieć lepsze wyczucie, kiedy go użyć.

Odpowiedz

246

Niedawno odpowiedział zasadzie to pytanie tutaj: (., Że linki Odpowiedź na niektórych giełdach GitHub z Miśko) https://stackoverflow.com/a/17239084/215945

Podsumowując:

  • jeśli kod jest w kolejce za pomocą $ evalAsync z dyrektywy, powinien działać po DOM został zmanipulowany przez Angular, ale przed przeglądarka renderuje
  • jeśli kod jest w kolejce za pomocą $ evalAsync z kontrolera, należy go uruchomić przed DOM został manipulowany przez kątowe (a przed przeglądarce czyni) - rzadko chcesz to
  • jeśli kod jest w kolejce za pomocą $ Timeout, należy go uruchomić po DOM zostało zmanipulowane przez kątowe i po renderuje przeglądarki (co może powodować migotanie w niektórych przypadkach)
+15

Dziękuję za wyjaśnienie. Jednej rzeczy nie jestem pewien, czy rozumiem. Dlaczego ma to wpływ na to, że dzwonisz do $ evalAsync z kontrolera lub dyrektywy? AsyncQueue nie wie, czy został zarejestrowany z kontrolera lub dyrektywy, po prostu umieszcza go w kolejce na bieżącym zasięgu. Czy ma to związek, gdy rzeczy działają w kontrolerze a kontrolerze? Po prostu chcę zrozumieć tę część. – dnc253

+0

@ dnc253, Nie spojrzałem na kod Angular, więc nie znam odpowiedzi na twoje (dobre) pytanie. Mam nadzieję, że ktoś inny może komentować. –

+15

"z dyrektywy" oznacza "z funkcji łączenia dyrektywy"? Czy to prawda, że ​​zachowanie jest wykonywane przy użyciu metody linku lub kontrolera dyrektywy? – SimplGy

52

Dla tych budujących złożonych aplikacji, należy pamiętać, że istnieje to jest wydajność im pakt na twój wybór. Również chciałbym zakończyć Mark odpowiedź więcej szczegółów technicznych:

  • $ Timeout (zwrotna) będzie czekać na prąd strawić cyklu do zrobienia (czyli kątowej aktualizacji wszystkich modelu i DOM), a następnie wykona swoje wywołanie zwrotne - potencjalnie wpływające na model kątowy - a następnie uruchom pełny $apply w katalogu głównym $ scope, i ponownie wszystko zmieści.

  • $ evalAsync (callback), z drugiej strony doda wywołanie zwrotne do bieżącego lub następnego cyklu podsumowania. Oznacza to, że jeśli jesteś w ciągu cyklu (na przykład w funkcji wywołanej z jakiejś dyrektywy ng-click), to nie będzie czekać na nic, kod zostanie wykonany od razu. Jeśli jesteś w asynchronicznym wywołaniu, na przykład setTimeout, zostanie uruchomiony nowy cykl podsumowania ($apply).

Więc jeśli chodzi o występy to zawsze lepiej zadzwonić $evalAsync, chyba że jest to dla Ciebie ważne, że widok jest aktualne przed wykonaniem kodu, na przykład jeśli trzeba Dostęp do jakiegoś Domu atrybutów, takich jak szerokość elementów i tym podobne.

Jeśli chcesz więcej szczegółów na temat różnicy między $ limit czasu, $ evalAsync, $ strawienia, $ zastosować, zapraszam do zapoznania się moją odpowiedź na to inne pytanie: https://stackoverflow.com/a/23102223/1501926

Również należy przeczytać documentation:

$ evalAsync nie udziela żadnych gwarancji co do tego, kiedy wyrażenie zostanie wykonane, tylko że:

  • będzie wykonywał po funkcji, które zaplanowano OCENA n (najlepiej przed renderowaniem DOM).
  • co najmniej jeden cykl podsumowania $ zostanie wykonany po wykonaniu wyrażenia.

Uwaga: jeśli ta funkcja nazywa się poza cyklem $ strawienia, nowy $ strawić cyklu zostaną zaplanowane. Zaleca się jednak, aby zawsze wywoływać kod, który zmienia model z wywołania $ apply. Obejmuje to kod oceniany za pomocą $ evalAsync.

+0

Czy możesz wyjaśnić, dlaczego potrzebny jest $ timeout, jeśli chcę uzyskać dostęp do jakiegoś atrybutu DOM . Powiedzmy, że mam

Czy funkcja watch-ng-bind nie aktualizuje atrybutu domena w pamięci, rozumiem, że nie będzie miała szansy na odświeżenie widoku, dopóki cykl trawienia nie zostanie zakończony. –

+2

@SridharChidurala, ponieważ DOM ("HTML") jest aktualizowany podczas cyklu trawienia, musisz poczekać, aż zostanie to zrobione, zanim będziesz mógł przeczytać mofifications. Odradza to jednak Angular, powinieneś odczytywać 'x' bezpośrednio ze swojego zakresu, a nie z DOM, więc nie musisz czekać na nic. Powinieneś również lepiej użyć 'ng-style' z css zamiast przestarzałej własności' width'. Jeśli potrzebujesz dodatkowej pomocy, otwórz nowe pytanie na StackOverflow. – floribon