Ajout d'un exemple pour les appels http.
This commit is contained in:
22
package-lock.json
generated
22
package-lock.json
generated
@@ -18,6 +18,7 @@
|
|||||||
"@angular/platform-browser": "^15.1.0",
|
"@angular/platform-browser": "^15.1.0",
|
||||||
"@angular/platform-browser-dynamic": "^15.1.0",
|
"@angular/platform-browser-dynamic": "^15.1.0",
|
||||||
"@angular/router": "^15.1.0",
|
"@angular/router": "^15.1.0",
|
||||||
|
"angular-in-memory-web-api": "^0.15.0",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"zone.js": "~0.12.0"
|
"zone.js": "~0.12.0"
|
||||||
@@ -4382,6 +4383,19 @@
|
|||||||
"ajv": "^8.8.2"
|
"ajv": "^8.8.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/angular-in-memory-web-api": {
|
||||||
|
"version": "0.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular-in-memory-web-api/-/angular-in-memory-web-api-0.15.0.tgz",
|
||||||
|
"integrity": "sha512-T07vQTeBEGWfwZRM+jIooYgK4c8LR25I27otIthUkFINAREoPiBNogWDxlnROIeu1k2RrY3QJjMOYq7f62UcgA==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^15.0.0",
|
||||||
|
"@angular/core": "^15.0.0",
|
||||||
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ansi-colors": {
|
"node_modules/ansi-colors": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||||
@@ -15346,6 +15360,14 @@
|
|||||||
"fast-deep-equal": "^3.1.3"
|
"fast-deep-equal": "^3.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"angular-in-memory-web-api": {
|
||||||
|
"version": "0.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular-in-memory-web-api/-/angular-in-memory-web-api-0.15.0.tgz",
|
||||||
|
"integrity": "sha512-T07vQTeBEGWfwZRM+jIooYgK4c8LR25I27otIthUkFINAREoPiBNogWDxlnROIeu1k2RrY3QJjMOYq7f62UcgA==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ansi-colors": {
|
"ansi-colors": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"@angular/platform-browser": "^15.1.0",
|
"@angular/platform-browser": "^15.1.0",
|
||||||
"@angular/platform-browser-dynamic": "^15.1.0",
|
"@angular/platform-browser-dynamic": "^15.1.0",
|
||||||
"@angular/router": "^15.1.0",
|
"@angular/router": "^15.1.0",
|
||||||
|
"angular-in-memory-web-api": "^0.15.0",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"zone.js": "~0.12.0"
|
"zone.js": "~0.12.0"
|
||||||
|
|||||||
@@ -4,12 +4,17 @@ import {PromisesExampleComponent} from "./promises-example/promises-example.comp
|
|||||||
import {HomeComponent} from "./home/home.component";
|
import {HomeComponent} from "./home/home.component";
|
||||||
import {ObservablesExampleComponent} from "./observables-example/observables-example.component";
|
import {ObservablesExampleComponent} from "./observables-example/observables-example.component";
|
||||||
import {StateManagementExampleComponent} from "./state-management-example/state-management-example.component";
|
import {StateManagementExampleComponent} from "./state-management-example/state-management-example.component";
|
||||||
|
import {NetworkCallComponent} from "./network-call/network-call.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: HomeComponent
|
component: HomeComponent
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'network-call',
|
||||||
|
component: NetworkCallComponent
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'promises',
|
path: 'promises',
|
||||||
component: PromisesExampleComponent
|
component: PromisesExampleComponent
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ import {BackToHomeComponent} from './back-to-home/back-to-home.component';
|
|||||||
import {MatIconModule} from "@angular/material/icon";
|
import {MatIconModule} from "@angular/material/icon";
|
||||||
import {StateManagementExampleComponent} from './state-management-example/state-management-example.component';
|
import {StateManagementExampleComponent} from './state-management-example/state-management-example.component';
|
||||||
import {RestServicesModule} from "./core/rest-services/rest-services.module";
|
import {RestServicesModule} from "./core/rest-services/rest-services.module";
|
||||||
import {CarComponent} from './core/components/car/car.component';
|
|
||||||
import {ObservablesExampleModule} from "./observables-example/observables-example.module";
|
import {ObservablesExampleModule} from "./observables-example/observables-example.module";
|
||||||
import {CoreModule} from "./core/core.module";
|
import {CoreModule} from "./core/core.module";
|
||||||
|
import {NetworkCallModule} from "./network-call/network-call.module";
|
||||||
|
import {HttpClientInMemoryWebApiModule} from "angular-in-memory-web-api";
|
||||||
|
import {RestApiMockService} from "./core/rest-api-mock/rest-api-mock.service";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -33,7 +35,14 @@ import {CoreModule} from "./core/core.module";
|
|||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
RestServicesModule,
|
RestServicesModule,
|
||||||
ObservablesExampleModule
|
ObservablesExampleModule,
|
||||||
|
NetworkCallModule,
|
||||||
|
HttpClientInMemoryWebApiModule.forRoot(
|
||||||
|
RestApiMockService,
|
||||||
|
{
|
||||||
|
dataEncapsulation: false
|
||||||
|
}
|
||||||
|
)
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import {CommonModule} from '@angular/common';
|
|||||||
import {CarComponent} from "./components/car/car.component";
|
import {CarComponent} from "./components/car/car.component";
|
||||||
import {RestServicesModule} from "./rest-services/rest-services.module";
|
import {RestServicesModule} from "./rest-services/rest-services.module";
|
||||||
import {MaterialModule} from "./material.module";
|
import {MaterialModule} from "./material.module";
|
||||||
|
import {HttpClientInMemoryWebApiModule} from "angular-in-memory-web-api";
|
||||||
|
import {RestApiMockService} from "./rest-api-mock/rest-api-mock.service";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -12,13 +13,13 @@ import {MaterialModule} from "./material.module";
|
|||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RestServicesModule,
|
RestServicesModule,
|
||||||
MaterialModule
|
MaterialModule,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CarComponent,
|
CarComponent,
|
||||||
RestServicesModule,
|
RestServicesModule,
|
||||||
MaterialModule
|
MaterialModule
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
export class CoreModule {
|
export class CoreModule {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ import {NgModule} from "@angular/core";
|
|||||||
import {MatIconModule} from "@angular/material/icon";
|
import {MatIconModule} from "@angular/material/icon";
|
||||||
import {MatButtonModule} from "@angular/material/button";
|
import {MatButtonModule} from "@angular/material/button";
|
||||||
import {MatTooltipModule} from "@angular/material/tooltip";
|
import {MatTooltipModule} from "@angular/material/tooltip";
|
||||||
|
import {MatSnackBar, MatSnackBarModule} from "@angular/material/snack-bar";
|
||||||
|
import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
|
||||||
|
|
||||||
const IMPORTED_MATERIAL_MODULES = [
|
const IMPORTED_MATERIAL_MODULES = [
|
||||||
MatIconModule,
|
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatTooltipModule
|
MatIconModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
|
MatSnackBarModule,
|
||||||
|
MatTooltipModule,
|
||||||
]
|
]
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export interface Car {
|
export interface Car {
|
||||||
id: string;
|
id: number;
|
||||||
brand: string;
|
brand: string;
|
||||||
model: string;
|
model: string;
|
||||||
power: number;
|
power: number;
|
||||||
|
|||||||
37
src/app/core/rest-api-mock/rest-api-mock.service.ts
Normal file
37
src/app/core/rest-api-mock/rest-api-mock.service.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {InMemoryDbService} from "angular-in-memory-web-api";
|
||||||
|
import {Car} from "../model/car";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class RestApiMockService implements InMemoryDbService {
|
||||||
|
createDb() {
|
||||||
|
const cars: Car[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
brand: 'Toyota',
|
||||||
|
model: 'Yaris',
|
||||||
|
power: 12,
|
||||||
|
numberOfSeats: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
brand: 'Citroën',
|
||||||
|
model: 'DS',
|
||||||
|
power: 14,
|
||||||
|
numberOfSeats: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
brand: 'Renault',
|
||||||
|
model: 'Twingo',
|
||||||
|
power: 8,
|
||||||
|
numberOfSeats: 2
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
cars
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import {HttpClient} from "@angular/common/http";
|
import {HttpClient} from "@angular/common/http";
|
||||||
import {Car} from "../model/car";
|
import {Car} from "../model/car";
|
||||||
import {toPromise} from "../utils/promises.utils";
|
import {toPromise} from "../utils/promises.utils";
|
||||||
|
import {Observable} from "rxjs";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -12,7 +13,11 @@ export class CarRestService {
|
|||||||
private http: HttpClient
|
private http: HttpClient
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
findById(carId: string): Promise<Car> {
|
findById(carId: number): Promise<Car> {
|
||||||
return toPromise(this.http.get<Car>(`/cars/${carId}`));
|
return toPromise(this.findById$(carId));
|
||||||
|
}
|
||||||
|
|
||||||
|
findById$(carId: number): Observable<Car> {
|
||||||
|
return this.http.get<Car>(`/api/cars/${carId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ export interface Link {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const LINKS: Link[] = [{
|
const LINKS: Link[] = [{
|
||||||
|
label: 'Les appels réseaux - Promesses ou Observables ?',
|
||||||
|
icon: '🌍',
|
||||||
|
href: '/network-call'
|
||||||
|
}, {
|
||||||
label: 'Les promesses',
|
label: 'Les promesses',
|
||||||
icon: '🙏',
|
icon: '🙏',
|
||||||
href: '/promises'
|
href: '/promises'
|
||||||
|
|||||||
20
src/app/network-call/network-call.component.html
Normal file
20
src/app/network-call/network-call.component.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<div class="component">
|
||||||
|
<h1>Les appels réseaux - Promesses ou Observables ?</h1>
|
||||||
|
<div class="actions">
|
||||||
|
<button mat-raised-button
|
||||||
|
(click)="loadCar()"
|
||||||
|
[disabled]="isLoading$ | async">
|
||||||
|
Load the car
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="loading" *ngIf="isLoading$ | async">
|
||||||
|
<h2>Loading...</h2>
|
||||||
|
<mat-spinner></mat-spinner>
|
||||||
|
</div>
|
||||||
|
<ng-container *ngIf="isLoaded">
|
||||||
|
<h2>Car data</h2>
|
||||||
|
<div class="centered">
|
||||||
|
<app-car [value]="car"></app-car>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
7
src/app/network-call/network-call.component.scss
Normal file
7
src/app/network-call/network-call.component.scss
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.component {
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
76
src/app/network-call/network-call.component.ts
Normal file
76
src/app/network-call/network-call.component.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {BehaviorSubject, catchError, EMPTY, finalize, Observable, tap} from "rxjs";
|
||||||
|
import {Car} from "../core/model/car";
|
||||||
|
import {CarRestService} from "../core/rest-services/car.rest-service";
|
||||||
|
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||||
|
|
||||||
|
const CAR_ID = 1;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-network-call',
|
||||||
|
templateUrl: './network-call.component.html',
|
||||||
|
styleUrls: ['./network-call.component.scss']
|
||||||
|
})
|
||||||
|
export class NetworkCallComponent {
|
||||||
|
private isLoadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||||
|
isLoaded: boolean = false;
|
||||||
|
car?: Car;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private carRestService: CarRestService,
|
||||||
|
private snackBar: MatSnackBar
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
get isLoading$(): Observable<boolean> {
|
||||||
|
return this.isLoadingSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCar(): void {
|
||||||
|
this.loadThroughAPromise();
|
||||||
|
// this.loadThroughAnObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadThroughAPromise(): void {
|
||||||
|
this.isLoadingSubject.next(true);
|
||||||
|
this.isLoaded = false;
|
||||||
|
|
||||||
|
this.carRestService.findById(CAR_ID)
|
||||||
|
.then(car => {
|
||||||
|
this.car = car;
|
||||||
|
this.isLoaded = true;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log('An error occured while loading the car.', error);
|
||||||
|
this.snackBar.open(
|
||||||
|
'An error occured while loading the car.',
|
||||||
|
'Close',
|
||||||
|
{duration: 2000}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.finally(() => this.isLoadingSubject.next(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadThroughAnObservable(): void {
|
||||||
|
this.isLoadingSubject.next(true);
|
||||||
|
this.isLoaded = false;
|
||||||
|
|
||||||
|
this.carRestService.findById$(CAR_ID)
|
||||||
|
.pipe(
|
||||||
|
tap(car => {
|
||||||
|
this.car = car;
|
||||||
|
this.isLoaded = true;
|
||||||
|
}),
|
||||||
|
catchError(error => {
|
||||||
|
console.log('An error occured while loading the car.', error);
|
||||||
|
this.snackBar.open(
|
||||||
|
'An error occured while loading the car.',
|
||||||
|
'Close',
|
||||||
|
{duration: 2000}
|
||||||
|
);
|
||||||
|
return EMPTY;
|
||||||
|
}),
|
||||||
|
finalize(() => this.isLoadingSubject.next(false))
|
||||||
|
).subscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/app/network-call/network-call.module.ts
Normal file
21
src/app/network-call/network-call.module.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
import {NetworkCallComponent} from "./network-call.component";
|
||||||
|
import {CoreModule} from "../core/core.module";
|
||||||
|
import {HttpClientModule} from "@angular/common/http";
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
NetworkCallComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
CoreModule,
|
||||||
|
HttpClientModule
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
NetworkCallComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class NetworkCallModule {
|
||||||
|
}
|
||||||
@@ -6,5 +6,10 @@ import { Component } from '@angular/core';
|
|||||||
styleUrls: ['./observables-example.component.scss']
|
styleUrls: ['./observables-example.component.scss']
|
||||||
})
|
})
|
||||||
export class ObservablesExampleComponent {
|
export class ObservablesExampleComponent {
|
||||||
|
/*
|
||||||
|
Formulaires :
|
||||||
|
-> valueChanges / debounceTime etc...
|
||||||
|
Appel réseau -> pour voir la diff avec les promesses
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class SimpleObservableExempleComponent {
|
|||||||
|
|
||||||
addNewCar(): void {
|
addNewCar(): void {
|
||||||
const newCar: Car = {
|
const newCar: Car = {
|
||||||
id: `${Math.random() * 100}`,
|
id: Math.random() * 100,
|
||||||
brand: 'Toyota',
|
brand: 'Toyota',
|
||||||
model: 'Yaris',
|
model: 'Yaris',
|
||||||
power: 12,
|
power: 12,
|
||||||
|
|||||||
@@ -8,10 +8,17 @@ import {Car} from "../core/model/car";
|
|||||||
})
|
})
|
||||||
export class PromisesExampleComponent {
|
export class PromisesExampleComponent {
|
||||||
car?: Car = {
|
car?: Car = {
|
||||||
id: '1234567890',
|
id: 1,
|
||||||
brand: 'Toyota',
|
brand: 'Toyota',
|
||||||
model: 'Yaris',
|
model: 'Yaris',
|
||||||
power: 12,
|
power: 12,
|
||||||
numberOfSeats: 5
|
numberOfSeats: 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Async / Await -> + comparaison avec les then
|
||||||
|
// new Promise "à la main"
|
||||||
|
// les then chaînés
|
||||||
|
// catch (avec 1 ou plusieurs then) -> try/catch avec un await
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
|
|
||||||
html, body { height: 100%; }
|
html, body { height: 100%; }
|
||||||
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
|
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
|
||||||
|
|
||||||
|
.centered {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user