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();
}
}
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 dopromise.then(array => this.heroes = array);
. Notthis.heroes = promise.then(array => this.heroes = array);
– JB Nizet