0
votes

I'm working through the tour of heroes app alongside a Udemy class to get some exposure to Angular development. I'm new to this ecosystem, but I felt like I was getting the hang of it until step 6: observable data. https://angular.io/tutorial/toh-pt4#observable-data

I think I get the concept but of observables being like a stream for promises where they can be resolved multiple times in different places of the app.

Below is my hero.service.ts code. I went through step 6 & 7 without observables and was able to work fine, but I could not get the observable part to work.

import { Injectable } from '@angular/core';
import {Observable, of} from 'rxjs';
import {Hero} from './hero';
import {HEROES} from './heroes-list'
import {MessageService} from './message.service'

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

  constructor(private messageService: MessageService) { }
  // Non-observable synchronous code, uncommenting and running with the 
 //observable code commented works fine
 //  getHeroes() :Hero[]{
 //         this.messageService.add('HeroService: fetched heroes');
 //        return HEROES;
 // }
 // getHero(id: number) :Hero{
 //   this.messageService.add(`HeroService: Fetched hero id:${id}`);
 //   return HEROES.find(hero => hero.id === id);
 // }
  /*Observable bug */
  getHeroes() :Observable<Hero[]>{
        this.messageService.add('HeroService: fetched heroes');
        return of(HEROES);
  }
  getHero(id: number) :Observable<Hero>{
    this.messageService.add(`HeroService: Fetched hero id:${id}`);
    return of(HEROES.find(hero => hero.id === id));
  }

}

The error I get reads as follows:

ERROR in src/app/heroes/heroes.component.ts(26,5): error TS2322: Type 'Subscription' is not assignable to type 'Hero[]'. Property 'includes' is missing in type 'Subscription'.

Which prompts me to investigate the component file but the code lines up with what's in the examples, so I don't see what the issue is. Can anyone let me know what is wrong?

heroes.component.ts

import { Component, OnInit } from '@angular/core';
import {Hero} from '../hero';
import {HeroService} from '../hero.service';
@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  constructor(private heroService: HeroService) { }

 //  hero = {
 //        id:1,
 //        name: "Deku",
 //        power: "One For All",
 //        origin: "My Hero Academica"
 // }
 heroesList :Hero[];
 clickedHero:Hero;
 // onClick(hero: Hero): void{
 //       this.clickedHero = hero;
 // }
  getHeroes(): void {
        // this.heroesList = this.heroService.getHeroes()
        // Cannot subscribe for some reason
    this.heroesList = this.heroService.getHeroes().subscribe(heroes => this.heroesList = heroes);
  }
  ngOnInit() {
        this.getHeroes();
  }
}
1
Remove this.heroesList = . The heroes List is initialized inside the callback passed to subscribe(). And, as the message indicates, subscribe() returns a Subscription. So initializing an array with a Subscription doesn't make sense. Just like, with a promise, you would do promise.then(array => this.heroes = array);. Not this.heroes = promise.then(array => this.heroes = array);JB Nizet
Ah I see so subscription is kind of like a notification type for the observable that says "when request a completes do b". And inside of b is where I have the data i request and can assign it. Promises were tricky enough to learn but observables are another beast.Callat

1 Answers

2
votes

This line is wrong.

this.heroesList = this.heroService.getHeroes().subscribe(heroes => this.heroesList = heroes);

It should just be:

this.heroService.getHeroes().subscribe(heroes => this.heroesList = heroes);

In the subscribe block you already assign to your local heroesList