2013-01-09 12 views
18

Niedawno niektórzy współpracownicy i ja dyskutowaliśmy o tym, czy usługi AngularJS powinny mieć stan, czy nie. Wymyśliliśmy kilka argumentów za i przeciw niemu i chciałem uzyskać dodatkowe przemyślenia i opinie na ten temat. Podczas moich poszukiwań znalazłem this, ale wydaje się, że nie ma tu żadnej wyraźnej najlepszej praktyki. W świecie, który nie ma klienta, usługa nigdy nie powinna utrzymywać stanu, ale zaczynam myśleć, że może to być akceptowalne po stronie klienta, ponieważ jest to inny problem.Czy usługa kątowa ma stan?

Powody usług posiadających Stan:

  1. Usługa nie będzie dostępna przez wielu wątków. Każda przeglądarka będzie miała własną instancję usługi.
  2. Umożliwia usłudze utrzymanie stanu, którego dotyczy, zamiast przechowywać go w rootScope. obudowuje

Powody usług nie trzymać Stan:

  1. usługi nie są już idempotent. Funkcje wywołujące mogą zmieniać stan i dlatego mogą mieć różne wyniki podczas wywoływania w oparciu o stan usługi.
  2. Myślę, że ogólnie byłoby łatwiej przetestować.

Jednym ze sposobów, które mogłyby zająć nr 2 w sekcji „Usługi dla gospodarstwa państwowego” byłoby mieć obiektu AppState ustawiony na rootScope który zawiera aktualny stan aplikacji. Wtedy cały stan zostanie zebrany w jednym miejscu, a następnie po prostu wyciągniesz z niego to, czego potrzebujesz. Znalazłem to i zastanawiałem się,

Odpowiedz

9

W AngularJS, usługi are passed in via factory function. Zasadniczo są to obiekty, które mogą zawierać pewien stan (np. Do buforowania lub przechowywania danych potrzebnych do wykonywania ich działań).

Jedno dobre rozwiązanie, które może zająć oba wady posiadania/braku stanu, gdy usługa (która może być faktycznie funkcją), która zwraca obiekt, który zawiera stan.

Spójrz na służbie $http: można dostać wystąpienie tej usługi wywołującego

var x = $http({url:'...'}); 

a następnie zadzwonić przez

var result = x.get() //actually `$http.get` is shortcut of this operation 

samo z ngResource: przy użyciu usługi otrzymasz przedmiot z jakiegoś stanu który może wykonywać pożądane działania.

W zasadzie myślę, że jest to najlepsza opcja: od jednego punktu unika się "efektów ubocznych" przez ruchomy stan, który można zmodyfikować poprzez działania w oddzielny obiekt, nie zapisany w samej usłudze, ale może mieć określony stan w tym obiekcie aby móc przechowywać własne informacje (np. informacje o autorze itp.).

+0

Dobre punkty dotyczące $ http i $ resource. Poza tym podoba mi się twoja myśl o tylko stanie przechowywania, który nie byłby modyfikowany przez funkcje wywoływane w usłudze (z wyjątkiem może podczas inicjowania usługi). – testing123

13

To prawdopodobnie zależy od tego, co masz na myśli przez "stan", ale w wielu przypadkach myślę, że odpowiedź brzmi tak: usługi powinny stan wstrzymania.

Na przykład, jeśli masz usługę odpowiedzialną za komunikację z interfejsem API, usługa ta może utrzymywać stan uwierzytelnienia.

Nawiasem mówiąc, nie jestem pewien, ile idempotencji ma znaczenie dla usług AngularJS - są one singletonami iz natury mają pewien stan. Można (iw niektórych przypadkach musi) tworzyć idempotentne metody w usłudze, ale jest to osobny problem.

+0

Dobrze wiedzieć o utrzymaniu stanu uwierzytelnienia. Jeśli chodzi o uczynienie usługi idempotentną, miałem na myśli, jak wspomniałeś, posiadanie idempotentnych metod. Dzięki za odpowiedź. – testing123

+0

To, co najlepsze w utrzymywaniu tego stanu, oznacza, że ​​można użyć zmiennej referencyjnej. Dzięki temu możesz stworzyć przejrzysty opis złożonej struktury danych! – Exitos

1

IMO tak, usługi MOGĄ mieć stany. Mówię "puszka" jako usługa może być uważana za coś, co przypomina klasyczną obsługę klienta - dostawcę, ale może również oznaczać coś zupełnie innego, w angularJS. Jako element rootScope-y z jedną instancją w aplikacji, można go użyć na przykład do zarządzania stanem. W moim przypadku to pozwala mi upewnić się, że struktura stanu jest taka sama w wielu aplikacjach i chociaż ich indywidualna struktura stanu jest zdefiniowana dla każdego w bootstrapie, rzeczy takie jak stan sesji są zawsze takie same i aktualizowane, kiedy ten moduł jest zmieniany.

-4

Przyczyną tego, że usługi nie powinny mieć stanu, jest to, że prowadzi do warunków wyścigu, gdy masz wiele wątków uzyskujących dostęp do usługi.

Częstym problemem ze stanu w usługi jest:

  1. gwint 1 pisze do stanu
  2. gwint 2 pisze do stanu
  3. Wątek 1 odczytuje ze stanu
  4. gwint 2 czyta od stanu

Wątek 1 ma teraz niewłaściwą wartość.

Powiedziawszy to, javascript jest obecnie z jednym wątkiem, więc nie będziesz mieć problemów z dostępem do wątku w ten sposób. Byłbym jednak zmartwiony, gdybym miał usługę, w której wiele asynchronicznych wywołań $ http zapisywało do tej samej zmiennej usługi. Gdybym tylko mógł lepiej spać w nocy, spróbowałbym napisać wszystkie moje metody serwisowe, więc były to przejęcia dla rzeczywistych danych.

Zamiast utrzymywać stan usługi, można rozważyć umieszczenie stanu w zapleczu tak bardzo, jak to możliwe. Rzeczy takie jak "uwierzytelnione", a nawet szerokości i wysokości mogą być utrzymywane i wyszukiwane. Może to otworzyć pewne możliwości pozwalające użytkownikom na nawigację z dala od aplikacji, powrót i znalezienie wszystkich swoich preferencji w dalszym ciągu skonfigurowanych i zalogowanych. Możesz zapisać identyfikator sesji w pliku cookie i zapisać wszystkie te rzeczy na zapleczu.

Jeśli wybrałeś trasę do oddzielnego obiektu do zapisania, możesz wyemitować do niego $ z usługi, gdy coś w stanie się zmieni: how to emit events from a factory. Byłoby to miłym efektem ubocznym polegającym na tym, że wiele usług może modyfikować ujednolicony stan aplikacji, ponieważ stan nie jest przechowywany w żadnej usłudze (lub gorzej rozłożony na wiele usług).

+2

Sam to powiedziałeś, javascript jest jednowątkowy, więc nie ma warunków wyścigowych, nawet przez webworkerów, ponieważ webworkerzy mogą dzielić się referencjami do obiektów. Mówisz o zapleczu, ale warstwy prezentacji mają stany, które nie mają nic wspólnego z utrzymaniem. – mpm

Powiązane problemy