HttpModule和HttpClientModule之间的区别

239
哪个是在Angular应用程序中构建一个仅用于测试目的的模拟网络服务最好的选择?

7
HttpClient是现有的Angular HTTP API的进化版,它与其在单独的包中共存。 - jonrsharpe
1
我昨天在我的博客上写了一些关于它的新功能:http://blog.jonrshar.pe/2017/Jul/15/angular-http-client.html - jonrsharpe
4
https://angular.io/guide/http - yurzui
7
这篇教程使用 HttpModule,而 https://angular.io/guide/http 使用 HttpClientModule,但两者都没有解释应该在什么情况下使用哪个模块,也没有说明使用哪个版本的 Angular 才可以使用它们。 - Mickey Segal
5个回答

351

如果您使用的是Angular 4.3.x及以上版本,请使用来自HttpClientModuleHttpClient类:

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

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

 class MyService() {
    constructor(http: HttpClient) {...}
这是从@angular / http模块升级的http的升级版,具有以下改进:
- 拦截器允许将中间件逻辑插入到管道中。 - 不可变的请求/响应对象 - 用于请求上传和响应下载的进度事件
您可以在Insider's guide into interceptors and HttpClient mechanics in Angular中了解其工作原理。
此外请注意,旧的http client将被弃用。以下是提交消息官方文档的链接。
还要注意的是,旧的HTTP使用 Http 类令牌进行注入,而不是新的 HttpClient
import { HttpModule } from '@angular/http';

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

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

此外,新的HttpClient似乎在运行时需要tslib,因此您必须安装它npm i tslib并更新system.config.js(如果您正在使用SystemJS):

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

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

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

1
我正在尝试导入HttpClientModule。但是使用“npm start”命令安装的node_modules目录中没有'@angular/common/http'。你能帮忙吗? - Dheeraj Kumar
1
@DheerajKumar,您使用的是哪个版本?它仅在4.3.0及以上版本可用。 - Max Koretskyi
我从git下载了Angular快速入门。在package.json中,存在"@angular/common": "^4.3.0",但是没有@angular/common/http。 - Dheeraj Kumar
5
我遇到了完全相同的问题(我正在使用System.js)。 这篇答案缺少的一点是,你还需要在System.js中映射新的模块,方法如下:'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js', - Tyler O
我正在尝试使用HttpClient来设置使用“英雄之旅”教程构建的应用程序。据我所知,我已经正确地设置了所有内容,但是当我尝试运行最简单的单元测试时,我会收到一个错误,指出tslib丢失了。但实际上它并没有丢失。而且我已经像上面展示的那样在systemjs中指向它了... - Tad Donaghe
显示剩余6条评论

44

不想重复,但要以其他方式总结(新HttpClient添加的功能):

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

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

Angular中的新HttpClient简介


21
这是一个很好的参考资料,帮助我将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);
      });

添加拦截器

我还使用拦截器为每个请求添加我的授权令牌,参考链接.

具体操作如下:

@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);
    }
}

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


你需要在你的回答中包含相关信息,而不仅仅是一个链接。 - Michael

1
有一个库可以让你使用强类型回调函数的HttpClient
通过这些回调函数直接获取数据和错误信息。

A reason for existing

当您使用带有Observable的HttpClient时,您必须在代码的其余部分中使用.subscribe(x=>...)。这是因为Observable<HttpResponse<T>>HttpResponse绑定在一起。这紧密耦合http层代码的其余部分
此库封装了.subscribe(x => ...)部分,并仅通过Models公开数据和错误。使用强类型回调函数,您只需要在代码的其余部分中处理您的Models即可。该库称为angular-extended-http-clientGitHub上的angular-extended-http-client库 NPM上的angular-extended-http-client库 非常容易使用。

示例用法

强类型回调函数如下:

成功:

  • IObservable<T>
  • IObservableHttpResponse
  • IObservableHttpCustomResponse<T>

失败:

  • IObservableError<TError>
  • IObservableHttpError
  • IObservableHttpCustomError<TError>

将包添加到您的项目中并在应用程序模块中使用

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类型。

在这些强类型的回调函数中,您只需要处理您的模型。

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

此外,您仍然可以使用传统的方法从服务API返回Observable<HttpResponse<T>>。


0

HttpClient 是一个新的 API,它随着 4.3 版本一起发布,具有更新的 API,支持进度事件、默认的 JSON 反序列化、拦截器和许多其他出色的功能。在这里查看更多信息:https://angular.io/guide/http

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接