• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Angular Observable.subscribe() nie działa w serwisie

Object Storage Arubacloud
0 głosów
314 wizyt
pytanie zadane 4 października 2019 w JavaScript przez daniel1806 Obywatel (1,780 p.)

Witam.

W angularowej aplikacji utworzyłem serwis, którego zadaniem miało być odczytywanie parametru z routingu. Użyłem właściwości params obiektu ActivatedRoute, która jest Observable. Zasubskrybowałem ją i nie działa. Z tego co udało mi się wywnioskować, to callback przekazany do subscribe() odpala się tylko raz przy starcie aplikacji a potem już nie. Nie ważne ile razy zmieni się parametr w routingu. Czy dobrze myślę, że winna jest tu propertka params? Czy jej wartość jest ustalana tylko raz przy załadowaniu komponentu? Czy może problem polega na czymś innym? Z tego co widziałem w kursach Angulara, to można używać Observable w serwisach, więc dlaczego mi nie działa?

Poniżej wrzucam kod serwisu:

import { Injectable, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class LangCheckService {

  private id: any;

  constructor(private route: ActivatedRoute, private router: Router) {
    this.route.params.subscribe(param => {
      this.id = param['langId'];
      // Logi wstawione po to, żeby sprawdzić czy subscribe w ogóle wywołuje callbacka
      console.log(param['langId']);
      console.log('Wykonanie callbacka w subscribe');
    });
  }


  checkId() {
    if(this.id != 'pl' && this.id != 'en' && this.id != undefined) {
      this.router.navigate(['/404']);
    }
    else return this.id;
  }
}

Dodam tylko, że dokładnie ten sam kod użyty w komponencie działa bez zarzutu a w serwisie nie chce.

Z góry dzięki za pomoc.

Pozdrawiam.

2 odpowiedzi

+1 głos
odpowiedź 4 października 2019 przez Aisekai Nałogowiec (42,190 p.)
Według mnie w serwisie nie działa z jednego powodu: ActivatedRoute jest powiązany z komponentem. Twój serwis jest tworzony przy tworzeniu AppComponentu, więc dostaje ActivatedRoute AppComponentu. W komponencie działa, bo zmienia się komponent. ActivatedRoute lepiej wstrzykiwac w komponencie.

https://angular.io/api/router/ActivatedRoute
komentarz 4 października 2019 przez daniel1806 Obywatel (1,780 p.)
Dzięki :)

Czyli jednak problem nie leży po stronie serwisu. To w takim razie mam inne pytanie. Skoro odczyt parametru z routingu będzie wykonywany przez różne komponenty, a nie chcę powtarzać tego samego kodu, to jaki w tej sytuacji byłby najlepszy sposób żeby tą funkcjonalność wyodrębnić gdzieś na zewnątrz żeby każdy komponent zainteresowany parametrem mógł sobie zaimportować/wywołać odpowiednią metodę?
komentarz 4 października 2019 przez Aisekai Nałogowiec (42,190 p.)
Nie wiem w sumie. Serwis nie powinien nie powinien sam decydować skąd ma zostać pobrana wartość atrybutu (np z URL), tylko pozostawić możliwość tego wyboru np komponentowi. Według mnie pobieranie wartości z QueryParams czy Params w komponencie (nawet jeżeli wiąże się to z duplikowaniem kodu) nie jest złym sposobem. Alternatywą byłoby wstrzykiwanie dodatkowego serwisu, który byłby osobno tworzony dla każdego komponentu i oddelegowac tą logikę do niego. Tylko pytanie, czy jest sens aż tak kombinować?

PS: Funkcje nie funkcjonalność :D Funkcjonalność to pojęcie abstrakxyjne
komentarz 5 października 2019 przez daniel1806 Obywatel (1,780 p.)
Ok rozumiem. Jestem amatorem, więc czasem używam tej całej terminologii nie do końca poprawnie :)

Co do tej duplikacji kodu, to chyba tak właśnie zrobię, że puki co uznam, że na chwilę obecną jest to dobre rozwiązanie. Chyba, że kiedyś ktoś pokaże mi lepszy sposób. A może nawet twórcy Angulara w kolejnej wersji wprowadzą jakieś narzędzie, które pomoże zrobić to lepiej.

Tak czy inaczej dzięki za odpowiedzi i pomoc :)
0 głosów
odpowiedź 4 października 2019 przez Paweł Nąckiewicz Nałogowiec (48,990 p.)
Z tego co mi się wydaje, to w konstruktorze tego nie powinieneś robić (jeśli chcesz się do tego odwołać więcej niż jeden raz). Może zobacz co się stanie dla np onInita() lub onChange()?
komentarz 4 października 2019 przez daniel1806 Obywatel (1,780 p.)
Z tego co wiem, to Lifecycle Hooks, czyli zarówno OnInit jak i OnChange nie działają w ogóle w komponentach @Injectable, a zatem w żadnym serwisie się ich nie implementuje. Coś takiego znalazłem w sieci, ale nie jestem na 100% tego pewien.
komentarz 4 października 2019 przez Paweł Nąckiewicz Nałogowiec (48,990 p.)
a probowałeś EventEmitera?
komentarz 4 października 2019 przez daniel1806 Obywatel (1,780 p.)
Nie próbowałem. Nawet na to nie wpadłem i szczerze mówiąc na chwilę obecną nawet nie bardzo wiem jak w tym przypadku użyć EventEmitera. Musiałbym zajrzeć do dokumentacji.

Ale dzięki za sugestię, może to jest dobry trop.  :)

Podobne pytania

0 głosów
2 odpowiedzi 351 wizyt
pytanie zadane 2 marca 2020 w JavaScript przez Ehlert Ekspert (212,990 p.)
0 głosów
1 odpowiedź 260 wizyt
pytanie zadane 7 stycznia 2021 w JavaScript przez reken Początkujący (390 p.)
0 głosów
0 odpowiedzi 251 wizyt

92,679 zapytań

141,582 odpowiedzi

320,065 komentarzy

62,041 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...