Skip to content

14 HttpClientModule

该模块用于发送 Http 请求,用于发送请求的方法都返回 Observable 对象。

14.1 QuickStart

  1. 引入 HttpClientModule 模块
// app.module.ts
import { HttpClientModule } from '@angular/common/http';
  imports: [
    HttpClientModule, // http
  ],
  1. 注入 HttpClient 服务实例对象,用于发送请求
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-quick-start',
  templateUrl: './quick-start.component.html',
  styleUrls: ['./quick-start.component.css']
})
export class QuickStartComponent {

  constructor(private http: HttpClient) { }
}
  1. 发送请求

src/app/components/http-client/quick-start/quick-start.component.ts:

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-quick-start',
  templateUrl: './quick-start.component.html',
  styleUrls: ['./quick-start.component.css']
})
export class QuickStartComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    this.http.get('https://jsonplaceholder.typicode.com/users').subscribe(console.log)
  }


}

Screenshot 2025-02-10 at 15.26.32

14.2 请求方法

this.http.get(url [, options]);
this.http.post(url, data [, options]) ; 
this.http.delpte(url (, options]);
this.http.put(url, data [, options]);
this.http.get<Post[]>('/getAllPosts')
  .subscribe (response => console.log(response))

14.3 HttpParams Usage

  1. HttpParams类
/**
 * An HTTP request/response body that represents serialized parameters,
 * per the MIME type `application/x-www-form-urlencoded`.
 *
 * This class is immutable; all mutation operations return a new instance.
 *
 * @publicApi
 */
export declare class HttpParams {
    private map;
    private encoder;
    private updates;
    private cloneFrom;
    constructor(options?: HttpParamsOptions);
    /**
     * Reports whether the body includes one or more values for a given parameter.
     * @param param The parameter name.
     * @returns True if the parameter has one or more values,
     * false if it has no value or is not present.
     */
    has(param: string): boolean;
    /**
     * Retrieves the first value for a parameter.
     * @param param The parameter name.
     * @returns The first value of the given parameter,
     * or `null` if the parameter is not present.
     */
    get(param: string): string | null;
    /**
     * Retrieves all values for a  parameter.
     * @param param The parameter name.
     * @returns All values in a string array,
     * or `null` if the parameter not present.
     */
    getAll(param: string): string[] | null;
    /**
     * Retrieves all the parameters for this body.
     * @returns The parameter names in a string array.
     */
    keys(): string[];
    /**
     * Appends a new value to existing values for a parameter.
     * @param param The parameter name.
     * @param value The new value to add.
     * @return A new body with the appended value.
     */
    append(param: string, value: string | number | boolean): HttpParams;
    /**
     * Constructs a new body with appended values for the given parameter name.
     * @param params parameters and values
     * @return A new body with the new value.
     */
    appendAll(params: {
        [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
    }): HttpParams;
    /**
     * Replaces the value for a parameter.
     * @param param The parameter name.
     * @param value The new value.
     * @return A new body with the new value.
     */
    set(param: string, value: string | number | boolean): HttpParams;
    /**
     * Removes a given value or all values from a parameter.
     * @param param The parameter name.
     * @param value The value to remove, if provided.
     * @return A new body with the given value removed, or with all values
     * removed if no value is specified.
     */
    delete(param: string, value?: string | number | boolean): HttpParams;
    /**
     * Serializes the body to an encoded string, where key-value pairs (separated by `=`) are
     * separated by `&`s.
     */
    toString(): string;
    private clone;
    private init;
}
  1. HttpParamsOptions接口
/**
 * Options used to construct an `HttpParams` instance.
 *
 * @publicApi
 */
export declare interface HttpParamsOptions {
    /**
     * String representation of the HTTP parameters in URL-query-string format.
     * Mutually exclusive with `fromObject`.
     */
    fromString?: string;
    /** Object map of the HTTP parameters. Mutually exclusive with `fromString`. */
    fromObject?: {
        [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
    };
    /** Encoding codec used to parse and serialize the parameters. */
    encoder?: HttpParameterCodec;
}
  1. 使用示例

src/app/components/http-client/http-params-usage/http-params-usage.component.ts:

import { HttpClient, HttpParams } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-http-params-usage',
  templateUrl: './http-params-usage.component.html',
  styleUrls: ['./http-params-usage.component.css']
})
export class HttpParamsUsageComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    let params = new HttpParams({
      // fromObject: { name: 'sam', age: '20' } 
      fromString: 'name=sam&age=20'
    });
    params = params.append("sex", "female");
    this.http.get('https://jsonplaceholder.typicode.com/users', {
      params
    }).subscribe(console.log)
  }

}

Screenshot 2025-02-10 at 16.31.33

14.4 HttpHeaders Usage

请求头字段的创建需要使用HttpHeader类, 在类实例对象下面有各种操作请求头的方法.

/**
 * Represents the header configuration options for an HTTP request.
 * Instances are immutable. Modifying methods return a cloned
 * instance with the change. The original object is never changed.
 *
 * @publicApi
 */
export declare class HttpHeaders {
    /**
     * Internal map of lowercase header names to values.
     */
    private headers;
    /**
     * Internal map of lowercased header names to the normalized
     * form of the name (the form seen first).
     */
    private normalizedNames;
    /**
     * Complete the lazy initialization of this object (needed before reading).
     */
    private lazyInit;
    /**
     * Queued updates to be materialized the next initialization.
     */
    private lazyUpdate;
    /**  Constructs a new HTTP header object with the given values.*/
    constructor(headers?: string | {
        [name: string]: string | string[];
    });
    /**
     * Checks for existence of a given header.
     *
     * @param name The header name to check for existence.
     *
     * @returns True if the header exists, false otherwise.
     */
    has(name: string): boolean;
    /**
     * Retrieves the first value of a given header.
     *
     * @param name The header name.
     *
     * @returns The value string if the header exists, null otherwise
     */
    get(name: string): string | null;
    /**
     * Retrieves the names of the headers.
     *
     * @returns A list of header names.
     */
    keys(): string[];
    /**
     * Retrieves a list of values for a given header.
     *
     * @param name The header name from which to retrieve values.
     *
     * @returns A string of values if the header exists, null otherwise.
     */
    getAll(name: string): string[] | null;
    /**
     * Appends a new value to the existing set of values for a header
     * and returns them in a clone of the original instance.
     *
     * @param name The header name for which to append the values.
     * @param value The value to append.
     *
     * @returns A clone of the HTTP headers object with the value appended to the given header.
     */
    append(name: string, value: string | string[]): HttpHeaders;
    /**
     * Sets or modifies a value for a given header in a clone of the original instance.
     * If the header already exists, its value is replaced with the given value
     * in the returned object.
     *
     * @param name The header name.
     * @param value The value or values to set or override for the given header.
     *
     * @returns A clone of the HTTP headers object with the newly set header value.
     */
    set(name: string, value: string | string[]): HttpHeaders;
    /**
     * Deletes values for a given header in a clone of the original instance.
     *
     * @param name The header name.
     * @param value The value or values to delete for the given header.
     *
     * @returns A clone of the HTTP headers object with the given value deleted.
     */
    delete(name: string, value?: string | string[]): HttpHeaders;
    private maybeSetNormalizedName;
    private init;
    private copyFrom;
    private clone;
    private applyUpdate;
}

src/app/components/http-client/http-headers-usage/http-headers-usage.component.ts:

import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-http-headers-usage',
  templateUrl: './http-headers-usage.component.html',
  styleUrls: ['./http-headers-usage.component.css']
})
export class HttpHeadersUsageComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    let headers = new HttpHeaders({
      test: "Hello"
    })
    this.http.get('https://jsonplaceholder.typicode.com/users', {
      headers
    }).subscribe(console.log)
  }
}

Screenshot 2025-02-10 at 16.57.57

14.5 Response Content

declare type HttpObserve = 'body' | 'response';
// response 读取完整响应体
// body 读取服务器端返回的数据

src/app/components/http-client/http-response-content/http-response-content.component.ts

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-http-response-content',
  templateUrl: './http-response-content.component.html',
  styleUrls: ['./http-response-content.component.css']
})
export class HttpResponseContentComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    let headers = new HttpHeaders({
      test: "Hello"
    })
    this.http.get('https://jsonplaceholder.typicode.com/users', {
      observe: 'body'
    }).subscribe(console.log)
  }

}

Screenshot 2025-02-10 at 17.07.12

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-http-response-content',
  templateUrl: './http-response-content.component.html',
  styleUrls: ['./http-response-content.component.css']
})
export class HttpResponseContentComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    let headers = new HttpHeaders({
      test: "Hello"
    })
    this.http.get('https://jsonplaceholder.typicode.com/users', {
      // observe: 'body',
      observe: 'response',
    }).subscribe(console.log)
  }

}

Screenshot 2025-02-10 at 17.08.08

14.6 Interceptors

拦截器是 Angular 应用中全局捕获和修改 HTTP 请求和响应的方式。(Token、Error)拦截器将只拦截使用 HttpClientModule 模块发出的请求。

ng g interceptor <name>

Screenshot 2025-01-26 at 16.51.53

14.6.1 Request Interceptor

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
     constructor(){}
     // 拦截方法
     intercept(
        // unknown 指定请求体(body)的类型
        request: HttpRequest<unknown>, 
    next: HttpHandler
        // unknown 指定响应内容(body)的类型
    ): Observable<HttpEvent<unknown>>{
        // 克隆并修改请求头
        const req = request.clone({
            setHeaders: {
                Authorization: "Bearer xxxxxxx"
            }
    })
        // 通过回调函数将修改店的请求头回传给应用
        return next.handle(req)
    }
}

ng g interceptor components/http-client/http-interceptors/auth

src/app/components/http-client/http-interceptors/auth.interceptor.ts:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() { }
  // 拦截方法
  intercept(
    // unknown 指定请求体(body)的类型
    request: HttpRequest<unknown>,
    next: HttpHandler
    // unknown 指定响应内容(body)的类型
  ): Observable<HttpEvent<unknown>> {
    // 通过回调函数将修改店的请求头回传给应用
    return next.handle(request);
  }
}

Screenshot 2025-02-10 at 17.30.38

14.6.2 Response Interceptor

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor() {}
    // 拦截方法
    intercept(
        request: HttpRequest<unknown>,
        next: HttpHandler
    ): Observable<any> {
        return next.handle(request).pipe(
            retry(2), // 重试2次
            catchError((error: HttpErrorResponse) => throwError(error))
        )
    }
}

14.6.3 Interceptor inject

import { AuthInterceptor } from "./auth.interceptor" 
import { HTTP_INTERCEPTORS } from "@angular/common/http"
@NgModule({
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: AuthInterceptor,
    multi: true
  }],
})

Screenshot 2025-02-10 at 17.33.06

Screenshot 2025-02-10 at 17.38.24

Screenshot 2025-02-10 at 17.38.40

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() { }
  // 拦截方法
  intercept(
    // unknown 指定请求体(body)的类型
    request: HttpRequest<unknown>,
    next: HttpHandler
    // unknown 指定响应内容(body)的类型
  ): Observable<HttpEvent<unknown>> {
    // 通过回调函数将修改店的请求头回传给应用
    let req = request.clone({
      setHeaders: {
        hello: "world"
      }
    }
    );
    return next.handle(req);
  }
}

Screenshot 2025-02-10 at 17.40.45

Screenshot 2025-02-10 at 17.42.05

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() { }
  // 拦截方法
  intercept(
    // unknown 指定请求体(body)的类型
    request: HttpRequest<unknown>,
    next: HttpHandler
    // unknown 指定响应内容(body)的类型
  ): Observable<HttpEvent<unknown>> {
    // 通过回调函数将修改店的请求头回传给应用
    let req = request.clone({
      method: "post",
      setHeaders: {
        hello: "world"
      }
    }
    );
    return next.handle(req);
  }
}

Screenshot 2025-02-10 at 17.41.49

src/app/components/http-client/http-interceptors/auth.interceptor.ts:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable, retry } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor() { }
  // 拦截方法
  intercept(
    // unknown 指定请求体(body)的类型
    request: HttpRequest<unknown>,
    next: HttpHandler
    // unknown 指定响应内容(body)的类型
  ): Observable<HttpEvent<unknown>> {
    // 通过回调函数将修改店的请求头回传给应用
    let req = request.clone({
      // method: "post",
      setHeaders: {
        hello: "world"
      }
    }
    );
    return next.handle(req).pipe(retry(2));
  }
}

src/app/components/http-client/http-response-content/http-response-content.component.ts:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-http-response-content',
  templateUrl: './http-response-content.component.html',
  styleUrls: ['./http-response-content.component.css']
})
export class HttpResponseContentComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    let headers = new HttpHeaders({
      test: "Hello"
    })
    this.http.get('https://0jsonplaceholder.typicode.com/users', { // link change
      // observe: 'body',
      observe: 'response',
    }).subscribe(console.log)
  }

}

Screenshot 2025-02-10 at 17.44.35

拦截器是个服务类

14.7 Angular Proxy

  1. 在项目的根目录下创建 proxy.conf.json 文件并加入如下代码
{
    "/api/*": {
        "target": "http://localhost:3070",
        "secure": false,
        "changeorigin": true
    }
}
  1. /api/*:在应用中发出的以/api 开头的请求走此代理
  2. target: 服务器端 URL
  3. secure:如果服务器端 URL的协议是 https,此项需要为 true
  4. changeOrigin:如果服务器端不是localhost,此项需要为 true

  5. 指定 proxy 配置文件(方式一)

package.json:

{
  "name": "angular-study",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.conf.json",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  1. 指定 proxy 配置文件(方式二)
     "serve": {
     "options": {
     "proxyConfig": "proxy.conf.json"
     } ,
    

src/app/components/http-client/http-proxy/http-proxy.component.ts:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-http-proxy',
  templateUrl: './http-proxy.component.html',
  styleUrls: ['./http-proxy.component.css']
})
export class HttpProxyComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    let headers = new HttpHeaders({
      test: "Hello"
    })
    this.http.get("http://localhost:3000/token").subscribe(console.log);
  }

}

Screenshot 2025-02-10 at 18.48.25

proxy.conf.json:

{
    "/token": {
        "target": "http://localhost:3000",
        "secure": false,
        "changeOrigin": true,
        "logLevel": "debug"
    }
}

package.json:

{
  "name": "angular-study",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.conf.json",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },

ng serve --proxy-config proxy.conf.json

src/app/components/http-client/http-proxy/http-proxy.component.ts:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-http-proxy',
  templateUrl: './http-proxy.component.html',
  styleUrls: ['./http-proxy.component.css']
})
export class HttpProxyComponent implements OnInit {

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    let headers = new HttpHeaders({
      test: "Hello"
    })
    this.http.get("/token").subscribe(console.log);
  }

}

Screenshot 2025-02-10 at 18.58.23