Maintenant que l’on a une application qui fonctionne bien, si si, elle fonctionne bien, et en plus, elle est sexy, nous allons passer à la vitesse supérieure.
Et oui, actuellement, nous avons utilisé un tableau sensé représenter tous les clones qui viennent de la base de l’étoile noire.
C’est super, mais en vrai, on va avoir d’une base de données pour ça, et donc un web service (une API) pour ça !
Comprendre la décoration @Injectable()
Plutôt que devoir instancier à chaque un Service, une classe que nous aurions besoin, nous pourrions penser un système qui charge au démarrage les classes, et inspecte les constructeurs, pour vérifier si cette classe est demandé par une autre classe.
Hmmm dit comme ça, ça semble trop théorique.
Architecture lasagne et isolation
Notre souhait c’est d’avoir des classes qui ont des responsabilités uniques. Ces classes vont être appelées pas d’autres classes, dans le principe de délégation.
Ainsi, prenons un logger que nous voudrions appeler dans notre composant. Nous avons deux choix :
- Instancier dans notre composant cette classe de Logger.
- L’instancier en statique au démarrage du projet et l’appeler dans notre composant comme si elle existait.
OK, l’idée est techniquement réalisable.
Rajoutons notre souhait de toujours tester ce que l’on fait.
Dans les principes de tests, nous ne devons tester que la classe en cours. Toute classe autour devra être testée elle aussi par des tests, oui, mais d’autres tests.
Donc nous devons isoler la classe de tout autre composant, classe, autre point qui pourrait empêcher de prouver nos résultats de tests à 100%.
Injection de dépendances
Arrive ici la notion d’injection de dépendances.
Ce principe respecte le pattern SOLID de toute architecture objet. Ne pas penser instance, mais penser interface. Ne pas penser Un seul bloc mais plusieurs qui ont chacun leur responsabilité.
Ici, nous allons donc indiquer au moteur d’injection de notre AppModule qu’il y a un Service injectable.
Création de notre service injectable
Ainsi, tout service qui sera injecté devra être décoré de @Injectable.
import { Injectable } from ‘@angular/core’;
import { Hero } from ‘../models/hero’;
import { HEROES } from ‘../models/mock-heroes’;
@Injectable({
providedIn: ‘root’
})
export class HeroService {
constructor() { }
getHeroes(): Hero[] {
return HEROES;
}
}
NOTE : Le providedIn: ‘root’ nous indique que c’est le moteur global d’injection qui sera chargera d’instancier une instance unique de cette classe.
NOTE : Le providedIn est une nouveauté de la version 6 d’Angular.
Suivre le guide de migration d’une version à l’autre
Si vous souhaitez avoir toutes les étapes de migration d’une version à l’autre. Voici le site qu’il vous faut : Angular upgrade guide.
A préciser dans le Module
Nous allons utiliser ici la partie provider du module :
@NgModule({
declarations: [
AppComponent,
HeroesComponent,
HeroDetailComponent
],
imports: [
BrowserModule,
FormsModule // allow you to use for example [(ngModel)]= » »
],
providers: [HeroService],
bootstrap: [AppComponent]
})
export class AppModule { }
Injection automatique de l’instance
Grâce à tout ceci, à chaque fois que le moteur d’injection va détecter la déclaration d’une variable du type injectable, il va utiliser la bonne instance … tout seul !
export class HeroesComponent implements OnInit {
heroes: Hero[];
selectedHero: Hero;
constructor(private _heroService: HeroService) { }
ngOnInit() {
this.heroes = HEROES;
}
onSelect(hero: Hero): void {
console.log(‘====> selecting’);
console.log(hero);
this.selectedHero = hero;
}
}
De la nécessité de rendre notre service Observable
Pour l’instant, notre service renvoie des données mockées (de fausses données).
Qui plus est, il les renvoie sans attendre, et surtout, surtout, de manière synchrone : quelque soit le temps qu’il faut pour construire la liste, il va attendre que la liste entière se construise !
Et ça, ça n’est pas bien.
Ca peut aller quand on a une liste qui a été créée en dur. Cependant, lorsque nous appellerons notre webservice, ça n’ira pas du tout !
Il vaut mieux envoyer la requête, et profiter du principe asynchrone.
Or, dès qu’on récupère le retour, nous devons mettre à jour notre Vue.
Dans le même principe des Promises, nous allons nous attacher à une Observable. Nous pourrons nous détacher, annuler la demande, …
Utilisation de l’Observable
-
- Importez la librairie dans votre fichier : import { Observable, of } from ‘rxjs’;
- Changez la signature et le corps de la méthode :
export class HeroService {
constructor() { }
getHeroes(): Observable<Hero[]> {
return of(HEROES);
}
}
NOTE: le of permet de transformer n’importe quelle donnée en Observable.
Il nous restera alors à changer l’appel dans le Component appelant la méthode getHeroes :
getHeroes(): void {
this._heroService.getHeroes().subscribe(heroesList => this.heroes = heroesList);
}
NOTE : Pour utiliser une Observable, nous devons y souscrire.