javascript - Angular sľub z ActivatedRoute nefunguje s Typescript await


Na prístup k komponentom v aktuálnej ceste URL v mojej aplikácii funguje nasledovné:

constructor(private route: ActivatedRoute) { }
...
load() {
    this.route.params.subscribe((params) => {
      const id = +params['id'];
      console.log('got parameter', id);
 ... etc

Toto je učebnicový prípad a premenná id sa nastaví podľa očakávania. Ale ja chcem použiť elegantnejšiu formu await a nefunguje to. (Samozrejme, že za tým bude nasledovať reťazec await príkazov.) Takto:

async load() {
    try {
      console.log('getting parameters');
      const params = await this.route.params.toPromise();
      console.log('got params', params);
      const id = +params['id'];
  ... etc

To, čo dostanem, je výstup z prvého volania console.log(), ale druhé sa nikdy nezobrazí. A samozrejme, premenná id sa nenastaví a zvyšok kódu sa nikdy nevykoná.

Dokumentácia a fungujúci kód uvádza, že this.route.params je Observable, ktorý by mal byť možné previesť na Promise cez toPromise() a tým pádom použiť s Typescript async/await. Používam await príkazy s Observables, ktoré pochádzajú z modulu HttpClient, úplne bez problémov.

Ale nefunguje to. Niekto vie prečo?

Odpoveď č. 1

Základná odpoveď je: Máte tu nekontrolovateľné závodné podmienky

Keď pristupujete k Observable route.params, je celkom normálne, že ešte nie je dokončený. Zavolanie toPromise() na ňom v tomto okamihu povedie k neustále čakajúcemu Promise a toto je problém, ktorému čelíte.

Ak nie ste viazaní na používanie tohto konštruktu async await, nechajte ho a radšej priamo synchronne pristúpte k params.id cez ActivatedRouteSnapshot.

ngOnInit() {
    const id: string = route.snapshot.params.id;
}

Odpoveď č. 2

Apropos AlanObjectovej otázky ...prečo ActivatedRoute používa Observables na prvom mieste..., dôvod je, že ngOnInit() sa volá len pri inicializácii komponentu, teda keď je vytvorený. Predstavte si, že váš komponent sa používa na zobrazenie detailov položky s routou ako /item/123, kde 123 je aktuálne ID položky.

Teraz, ak by váš komponent implementoval aj odkazy Predchádzajúci a Nasledujúci, ktoré navigujú na /item/122 a /item/124, komponent by nebol znovu inicializovaný. V takýchto prípadoch by ste potrebovali odber alebo iný spôsob, ako získať aktualizované ID a súvisiace údaje.

Súvisiace články