mika-el
5/9/2018 - 1:47 PM

HttpClient

Observables http

Here are some key things to bear in mind regarding this particular type of Observables returned by the HTTP module:

  • if we don't subscribe to these observables, nothing will happen
  • if we subscribe multiple times to these observables, multiple HTTP requests will be triggered (see this post for more details)
  • This particular type of Observables are single-value streams: If the HTTP request is successful, these observables will emit only one value and then complete
  • these observables will emit an error if the HTTP request fails, more on this later

If we subscribe multiple times to these observables, multiple HTTP requests will be triggered

There are several ways to avoid this situation, but there was recently an operator added to RxJs specifically to tackle this use case - the shareReplay operator.

const httpGet = this.http.get("/courses.json").pipe(
  shareReplay()
);

httpGet.subscribe(
  res => { console.log('1', res) }
);

httpGet.subscribe(
  res => { console.log('2', res) }
);

Combiner le résultat de requêtes HTTP parallèles avec l'opérateur forkJoin:

const parallel$ = Observable.forkJoin(
  this.http.get('/courses/-KgVwEBq5wbFnjj7O8Fp.json'),
  this.http.get('/courses/-KgVwECOnlc-LHb_B0cQ.json')
);

parallel$.subscribe(
  values => { console.log("all values", values)}
);

Requêtes sequencielles avec l'opérateur switchMap :

const sequence$ = this.http.get<any>('/courses/-KgVwEBq5wbFnjj7O8Fp.json').pipe(
  switchMap(course => {
    course.description += ' - TEST ';
    return this.http.put('/courses/-KgVwEBq5wbFnjj7O8Fp.json', course)
  })
);
sequence$.subscribe();

Erreurs

Capture simple de l'erreur http :

this.http.get('https://api.github.com/users/seeschweiler').subscribe(
  data => {
    console.log(data);
  },
  err => {
    console.log("Error occured.")
  });
}

Capture et récupération de l'erreur http :

this.http.get('https://api.github.com/users/seeschweiler').subscribe(
  data => {
    console.log(data);
  },
  (err: HttpErrorResponse) => {
      if (err.error instanceof Error) {
        console.log("Client-side error occured.");
      } else {
        console.log("Server-side error occured.");
      }
  });
}

GET

Requete get simple :

this.http.get('https://api.github.com/users/seeschweiler').subscribe(data => {
    console.log(data);
  });
}

cast de la réponse :

interface UserResponse {
  login: string;
  bio: string;
  company: string;
}

this.http.get<UserResponse>('https://api.github.com/users/seeschweiler').subscribe(data => {
  console.log("User Login: " + data.login);
  console.log("Bio: " + data.bio);
  console.log("Company: " + data.company);
});

Headers

ajout de headers à un appel GET:

const headers = new HttpHeaders()
  .set("X-CustomHeader", "custom header value");

return this.http.get("/courses.json", {headers});

Ce type d'appel ne marchera pas car HttpHeaders est immutable donc set retournera un nouvel object HttpParams :

const headers = new HttpHeaders()

headers.set("X-CustomHeader", "custom header value");
headers.set("X-CustomHeader2", "custom header value 2");

HttpParams

Envoi de paramètres GET:

import { HttpParams } from "@angular/common/http";
...

const params = new HttpParams()
    .set('orderBy', '"$key"')
    .set('limitToFirst', "1");
    
// On peut aussi construire avec du text si on a dèjà les paramètres prêts:
const params = new HttpParams({
  fromString: 'orderBy="$key"&limitToFirst=1'
});

return this.http.get("/courses.json", {params});

Ce type d'appel ne marchera pas car HttpParams est immutable donc set retournera un nouvel object HttpParams :

const params = new HttpParams();
params.set('orderBy', '"$key"')
params.set('limitToFirst', "1");

Interceptor

Le service

@Injectable()
export class GithubAuthInterceptor implements HttpInterceptor {
  intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authReq = req.clone({
      headers: req.headers.set('Authorization', 'token <your GitHub token>')
    });
    return next.handle(authReq);
  }
}

Le provider pour un singleton dans AppModule :

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [{
    provide: HTTP_INTERCEPTORS, //needs to be set to multi to tell Angular that HTTP_INTERCEPTORS is an array of values, rather than a single value
    useClass: GithubAuthInterceptor,
    multi: true
  }],
  bootstrap: [AppComponent]
})
export class AppModule { }

POST

Simple requete POST:

const reqSubcriber = this.http.post('http://jsonplaceholder.typicode.com/posts', {
  title: 'foo',
  body: 'bar',
  userId: 1
}).subscribe(
  res => { console.log(res) },
  err => { console.log("Error occured") }
);