[Angular] Jak poprawnie pobrać dane z service tylko raz dla danego modułu?

0

Hej!
Chciałbym, aby dane pobierane w konkretnym service, były pobierane tylko raz dla danego modułu. Aktualnie zrobiłem to w taki sposób, że wstrzykuje service do constructora componentu danego modułu. Dzięki temu odpala mi się constructor service i dane pobierają się tylko raz. Tyle, że w constructorze componentu przekazuje zmienną service, która nie jest używana (potrzebne mi samo wywołanie constructora service poprzez wstrzyknięcie).

Średnio podoba mi się to rozwiązanie.

W jaki inny sposób mógłbym wywoływać pobieranie danych w konkretnym service tylko raz?

Pozdrawiam

0

Nie wiem zalezy od tego co oczekujesz ale masz kilka rozwiazan:
https://angular.io/api/core/APP_BOOTSTRAP_LISTENER
https://angular.io/api/core/APP_INITIALIZER

Zreszta twoje rozwiazanie nie jest glupie moze zamiast pobierac w kontruktorze zrobic jakis method typu Init()/Bootstrap() (wtedy Od razu wiesz o co chodzi bez patrzenia co robi konstruktor w serwisie) i po prostu w komponencie ktory dziala jako router-outlet inicializuj serwisy...

0

Jeżeli przy każdym odświeżeniu strony także chcesz ładować dane to app initializer wydaje się ok

2

Z ta roznica ze APP_INITIALIZER dziala jak delay przy bootstrap-ie aplikacji, APP_BOOTSTRAP_LISTENER dla kazdego moduly ktory bedzie uzyty bedziesz mogl pobrac jakies dane, jesli nie chcesz ich pobierac za kazdym razem a miec jakis cache lokalny typu local storage mozesz w serwisie uzyc ngx-cacheable (lub za pomoca service worker) wtedy to co pobierzesz w APP_LISTENER bedzie np mialo expire 10min i nie bedzie spowalnialo bootstrap aplikacji jesli nie ma takiej potrzeby (byc moze twoje dane rzadko sie zmieniaja)

0

Dzięki za odpowiedzi! Huh nie mam takiej wiedzy jak Wy, ale jest pewno ale.
Nie wiem czy dosyć jasno określiłem to co chcę uzyskać, a mianowicie:
Dla child modułu(wyłącznie) chciałbym, aby były pobierane dane (raz) z konkretnego service. Rozwiązanie z APP_INITIALIZER jest dedykowane tylko dla AppModule, bo to tam jest inicjowana aplikacja. Nie wiem jak z APP_BOOTSTRAP_LISTENER, ale pewnie podobnie? Próbowałem użyć i się nie udało.

Najprostsze rozwiązanie, którego obecnie użyłem, jest po prostu wstrzyknięcie w constructor modułu - service, który mnie interesuje i wywołanie jego metody. To działa ok, ale czy to najlepsze rozwiązanie, nie wiem.

Znalazłem wątek, w którym poruszany jest temat MODULE_INITIALIZER jak APP_INITIALIZER, a także constructora w module. Nie rozumiem jednak czy można importować MODULE_INITIALIZER z jakiejś biblioteki? Nie mogę znaleźć takiego info. Link:
https://github.com/angular/angular/issues/17606

W ostateczności zostanę przy constructorze.

Co sądzicie?

1

Tak na szybko:

  1. Serwis który trzymał by 2 zmienne (loaded oraz kolekcje danych) albo obiekt z takimi polami i metodę loadData. Zrobiłbym to na behaviorSubject i observable (strumienie były by publiczne, subjecty oczywiście prywatne)
  2. robisz guarda canLoad (jeśli używasz mechanizmu lazy loadingu dla modułów) albo canActivate
  3. podczepiasz guard canLoad pod routa ładującego konkretne moduły albo canActivate pod konkretne ścieżki
  4. w guardzie wstrzykujesz tamten serwis robisz coś takiego w metodzie canLoad/canActivate:
    return this.dataService.loaded$.pipe(
    tap(loaded => {
    if (!loaded) {
    this.dataService.loadData();
    }
    }),
    filter(loaded => loaded),
    take(1)
    );

Zauważ ze jeśli twój strumień loaded$ zwróci flagę true to przejdziesz dalej i przepuscisz nawigację dalej bez ponownego ładowania.

Serwis możesz wstrzyknąć sobie w dowolne potrzebne miejsce i skorzystać ze strumienia z danymi (tylko musisz mu określić dobry zasięg).

Jest to bardzo prosta obsługa pisana na telefonie także wybacz ewentualne literówki.

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