The most common way to get data from web services is through Http. And in this article we will see how this Http request in Angular 4.3 can be made through the new HttpClient.
Starting with version Angular 4.3, a new HttpClient has appeared. This article only describes a new client .
HttpClientModule
Httpclient
Httpmodule
Http
Note: The old http implementation still exists in 4.3, so make sure you are using the right one.
First of all, we need to import the HttpClientModule into the parent module. If you have a new Angular project, it will most likely be an AppModule. To import a module, simply add it to the imports section of the parent module.
src / app / app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; // , , import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent, ], imports: [ BrowserModule, HttpClientModule // ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
The correct approach when building an Angular application is to take out all HTTP requests from components to services in order to make them completely independent, and to wrap all requests in separate services. Then, for example, during testing it will be possible to make a mocke version of the service. And the code with this approach turns out to be more accurate.
Usually for services you get a separate folder in the module, where you will have a service, completely your choice.
Every service has a specific purpose. For example, if we want to request photos of cats via http, then our service will be called CatPictureService . The basis of the service will look something like this:
src / app / services / catPicture.service.ts
import { Injectable } from '@angular/core'; @Injectable() export class CatPictureService { constructor() { } }
To make an http request from our service, we need Angular HttpClient . We can easily add it through dependency injection (DI).
src / app / services / catPicture.service.ts
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable() export class CatPictureService { constructor(private httpClient: HttpClient) { } }
To make a request, we will add a new method to our service. Methods are usually called verbs. At the moment we will call the method "get". He will receive a photo of the cat at the URL.
public get(url: string): Observable<any>{ return this.httpClient.get(url); }
As you can see, Angular HttpClient is quite simple. All we need to do is call the get method and pass it the url. This get method returns an Observable object. This class is part of the rxjs library, which is used in many places in Angular. One example of use is HttpClient.
Like a promise (Promise), the observer (Observable) does not immediately contain values. Instead, it has a subscribe method (subscribe), where we can register a callback. This callback is called as soon as the result is available. In addition to the promise, Observable can return more than one value. You can reclaim the flow of results. But it does not matter for this lesson. In our case, Observable returns only one value.
So, how can we subscribe to an observer who was returned by our new method to get the actual value? This is pretty easy. We simply call the subscribe subscription method and register one (or two) methods for the callback. The first callback is called when the result is available. It gets the result as a parameter. The second callback starts when any error occurs with the request. As a parameter, it receives an error object.
Here is how it looks in code. I compiled a picService instance. You need to secure and request this service yourself.
this.picService.get('http://anyurl.com').subscibe(value =>{ // value - }, error => { // error - });
NOTE. You always need to subscribe (call the subscibe method) otherwise the request will not be made!
Http supports a huge selection of various options, headers and formats. To make all these different requests from the HttpClient, all its methods take the options object as an optional parameter.
Starting with Angular 4.3, the default response format is JSON. This makes using HttpClient very easy. You no longer need to analyze the answer manually. Angular does this for you.
Although JSON is the most common response format, there are many examples where you cannot use JSON. For example, when requesting photos of cats.
To avoid automatic analysis of the response, we can predefine the responseType property through the options object.
{ responseType: 'text' }
To add headers to the request, we use the headers property of the options object. For this, we need an HttpHeaders object. It contains all our heading definitions. Do not use the Headers object, as it is part of the old Http client.
const headers = new HttpHeaders({ 'Content-Type': 'application/json' }); const options = { headers: headers };
We can also define url parameters inside the options object. To do this, we need to create an HttpParams object. Thus, we do not need to add them to the url line.
const params = new HttpParams().set('id', '3'); const options = {params: params};
One of the new features of the new HttpClient is the ability to track the progress of the request. For example, if you want to upload a large file, you probably want to report the download progress to the user.
To do this, we need to break our query in a separate request object. To get progress, we need to set the reportProgress property to true .
import { Observable } from 'rxjs/Observable'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { HttpRequest } from "@angular/common/http"; import { Subject } from "rxjs/Subject"; import { HttpEventType } from "@angular/common/http"; import { HttpResponse } from "@angular/common/http"; public post(url: string, file: File): Observable<number>{ var subject = new Subject<number>() const req = new HttpRequest('POST', url, file, { reportProgress: true, }); this.httpClient.request(req).subscribe(event => { if (event.type === HttpEventType.UploadProgress) { const percentDone = Math.round(100 * event.loaded / event.total); subject.next(percentDone); } else if (event instanceof HttpResponse) { subject.complete(); } }); return subject.asObservable(); }
The post method returns an Observable object representing the loading progress.
Another great feature of the new HttpClient are interceptors. In some cases, you may need to change the request before it reaches the server. Or you want to change every answer. You can do this with the Interceptor. This is a kind of middleware between http-api and the actual request.
One common use case might be authentication. To get a response from the server, you often need to add some kind of authentication mechanism to the request. Of course, you can simply change the authorization header in your service. But this task is always the same, isn't it? This is always the same protocol. It never changes, even between applications. So why don't we write the logic once and reuse it everywhere?
Like a service, the interceptor is injectable.
import { Observable } from 'rxjs/Observable'; import {Injectable} from '@angular/core'; import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http'; @Injectable() export class AuthenticationInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { req.headers.append('Authorization', '<SOME-TOKEN>') return next.handle(req); } }
Since an application can have multiple interceptors, they are chained. The first element is called Angular. Subsequently, we are responsible for transmitting the request to the next interceptor. To do this, we call the handle method of the next element in the chain as soon as we finish.
Before we do this, we can change the request as we like. For example, add a token to the authorization header.
This example is by no means complete or reusable. But this should give you an idea of how to proceed from here.
Just like services, we also need to block interceptors. To do this, your parent module (AppModule) should look something like this:
src / app / app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; // , , import { HttpClientModule } from '@angular/common/http'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent, ], imports: [ BrowserModule, HttpClientModule // ], providers: [{ provide: HTTP_INTERCEPTORS, useClass: AuthenticationInterceptor, multi: true, }], bootstrap: [AppComponent] }) export class AppModule { }
Now we know how we can send or receive external data via http. We also learned what options we can use and how to track progress.
Hope you enjoyed this article.
Source: https://habr.com/ru/post/336280/
All Articles