【问题标题】:Difference between HttpModule and HttpClientModuleHttpModule 和 HttpClientModule 的区别
【发布时间】:2017-12-21 03:18:57
【问题描述】:

使用哪一个来构建一个模拟 Web 服务来测试 Angular 4 应用程序?

【问题讨论】:

标签: angular angular-httpclient angular2-http


【解决方案1】:

如果您使用的是 Angular 4.3.x 及更高版本,请使用 HttpClientModule 中的 HttpClient 类:

import { HttpClientModule } from '@angular/common/http';

@NgModule({
 imports: [
   BrowserModule,
   HttpClientModule
 ],
 ...

 class MyService() {
    constructor(http: HttpClient) {...}

它是http@angular/http模块的升级版本,具有以下改进:

  • 拦截器允许将中间件逻辑插入到管道中
  • 不可变的请求/响应对象
  • 请求上传和响应下载的进度事件

您可以在Insider’s guide into interceptors and HttpClient mechanics in Angular 中了解它的工作原理。

  • 类型化的同步响应正文访问,包括对 JSON 正文类型的支持
  • JSON 是假定的默认值,不再需要显式解析
  • 请求后验证和基于刷新的测试框架

今后旧的 http 客户端将被弃用。以下是commit messagethe official docs 的链接。

还要注意旧的http是使用Http类令牌而不是新的HttpClient注入的:

import { HttpModule } from '@angular/http';

@NgModule({
 imports: [
   BrowserModule,
   HttpModule
 ],
 ...

 class MyService() {
    constructor(http: Http) {...}

另外,新的HttpClient 似乎在运行时需要tslib,所以如果你使用SystemJS,你必须安装它npm i tslib 并更新system.config.js

map: {
     ...
    'tslib': 'npm:tslib/tslib.js',

如果使用 SystemJS,则需要添加另一个映射:

'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',

【讨论】:

  • 我正在尝试导入 HttpClientModule。但是我使用“npm start”命令安装的 node_modules 目录中不存在“@angular/common/http”。你能帮忙吗?
  • @DheerajKumar,您使用的是哪个版本?它仅在 4.3.0 及更高版本中可用
  • 我从 git 下载了 Angular 快速入门。并且在 package.json 中,存在 "@angular/common": "^4.3.0"。但没有@angular/common/http。
  • 删除node_modules文件夹并再次运行npm install
  • 我遇到了同样的问题(我正在使用 System.js)。这个答案中缺少的一件事是,您还需要在 system.js 中映射新模块,如下所示:'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',
【解决方案2】:

不想重复,只是换个方式总结一下(新HttpClient中新增的功能):

  • 从 JSON 到对象的自动转换
  • 响应类型定义
  • 事件触发
  • 标题的简化语法
  • 拦截器

我写了一篇文章,其中介绍了旧的“http”和新的“HttpClient”之间的区别。我们的目标是以最简单的方式解释它。

Simply about new HttpClient in Angular

【讨论】:

    【解决方案3】:

    这是一个很好的reference,它帮助我将我的http 请求切换到httpClient

    比较两者的差异并给出代码示例。

    这只是我在项目中将服务更改为 httpclient 时处理的一些差异(借用我提到的文章):

    导入

    import {HttpModule} from '@angular/http';
    import {HttpClientModule} from '@angular/common/http';
    

    请求和解析响应:

    @angular/http

     this.http.get(url)
          // Extract the data in HTTP Response (parsing)
          .map((response: Response) => response.json() as GithubUser)
          .subscribe((data: GithubUser) => {
            // Display the result
            console.log('TJ user data', data);
          });
    

    @angular/common/http

     this.http.get(url)
          .subscribe((data: GithubUser) => {
            // Data extraction from the HTTP response is already done
            // Display the result
            console.log('TJ user data', data);
          });
    

    注意:您不再需要显式提取返回的数据;默认情况下,如果你返回的数据是 JSON 类型,那么你不需要做任何额外的事情。

    但是,如果您需要解析任何其他类型的响应,例如文本或 blob,请确保在请求中添加 responseType。像这样:

    使用 responseType 选项发出 GET HTTP 请求:

     this.http.get(url, {responseType: 'blob'})
          .subscribe((data) => {
            // Data extraction from the HTTP response is already done
            // Display the result
            console.log('TJ user data', data);
          });
    

    添加拦截器

    我还使用拦截器将我的授权令牌添加到每个请求 reference

    像这样:

    @Injectable()
    export class MyFirstInterceptor implements HttpInterceptor {
    
        constructor(private currentUserService: CurrentUserService) { }
    
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
            // get the token from a service
            const token: string = this.currentUserService.token;
    
            // add it if we have one
            if (token) {
                req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
            }
    
            // if this is a login-request the header is 
            // already set to x/www/formurl/encoded. 
            // so if we already have a content-type, do not 
            // set it, but if we don't have one, set it to 
            // default --> json
            if (!req.headers.has('Content-Type')) {
                req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
            }
    
            // setting the accept header
            req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
            return next.handle(req);
        }
    }
    

    这是一个相当不错的升级!

    【讨论】:

    • 您需要在答案中包含相关信息,而不仅仅是链接
    【解决方案4】:

    有一个库允许您将 HttpClient 与强类型回调一起使用

    数据和错误可直接通过这些回调获得。

    当您将 HttpClient 与 Observable 一起使用时,您必须在其余代码中使用 .subscribe(x=>...)

    这是因为 ObservableHttpResponseT>>HttpResponse 绑定。

    http层您的代码的其余部分紧密结合

    这个库封装了 .subscribe(x => ...) 部分,只通过你的模型暴露数据和错误。

    使用强类型回调,您只需在其余代码中处理模型。

    该库名为 angular-extended-http-client

    angular-extended-http-client library on GitHub

    angular-extended-http-client library on NPM

    非常容易使用。

    示例用法

    强类型回调是

    成功:

    • IObservableT>
    • IObservableHttpResponse
    • IObservableHttpCustomResponseT>

    失败:

    • IObservableErrorTError>
    • IObservableHttpError
    • IObservableHttpCustomErrorTError>

    将包添加到您的项目和应用模块中

    import { HttpClientExtModule } from 'angular-extended-http-client';
    

    在@NgModule 导入中

      imports: [
        .
        .
        .
        HttpClientExtModule
      ],
    

    你的模型

    //Normal response returned by the API.
    export class RacingResponse {
        result: RacingItem[];
    }
    
    //Custom exception thrown by the API.
    export class APIException {
        className: string;
    }
    

    您的服务

    在您的服务中,您只需使用这些回调类型创建参数。

    然后,将它们传递给 HttpClientExt 的 get 方法。

    import { Injectable, Inject } from '@angular/core'
    import { RacingResponse, APIException } from '../models/models'
    import { HttpClientExt, IObservable, IObservableError, ResponseType, ErrorType } from 'angular-extended-http-client';
    .
    .
    
    @Injectable()
    export class RacingService {
    
        //Inject HttpClientExt component.
        constructor(private client: HttpClientExt, @Inject(APP_CONFIG) private config: AppConfig) {
    
        }
    
        //Declare params of type IObservable<T> and IObservableError<TError>.
        //These are the success and failure callbacks.
        //The success callback will return the response objects returned by the underlying HttpClient call.
        //The failure callback will return the error objects returned by the underlying HttpClient call.
        getRaceInfo(success: IObservable<RacingResponse>, failure?: IObservableError<APIException>) {
            let url = this.config.apiEndpoint;
    
            this.client.get(url, ResponseType.IObservable, success, ErrorType.IObservableError, failure);
        }
    }
    

    你的组件

    在您的组件中,您的服务被注入并调用 getRaceInfo API,如下所示。

      ngOnInit() {    
        this.service.getRaceInfo(response => this.result = response.result,
                                    error => this.errorMsg = error.className);
    
      }
    

    回调中返回的 responseerror 都是强类型的。例如。 responseRacingResponse 类型,errorAPIException

    您只在这些强类型回调中处理您的模型。

    因此,您的其余代码只知道您的模型。

    另外,您仍然可以使用传统路由并从 Service API 返回 ObservableHttpResponse<T&gt;>。

    【讨论】:

      【解决方案5】:

      HttpClient 是 4.3 附带的新 API,它更新了 API,支持进度事件、默认的 json 反序列化、拦截器和许多其他强大功能。在此处查看更多信息https://angular.io/guide/http

      Http 是较旧的 API,最终将被弃用。

      由于它们在基本任务中的用法非常相似,因此我建议使用 HttpClient,因为它是更现代且易于使用的替代方案。

      【讨论】:

        猜你喜欢
        • 2018-01-06
        • 1970-01-01
        • 2019-06-19
        • 1970-01-01
        • 2018-02-07
        • 2023-03-06
        • 1970-01-01
        • 1970-01-01
        • 2018-06-14
        相关资源
        最近更新 更多