试水新的Angular4 HTTP API

本文来自网易云社区


作者:梁月康

原文:https://netbasal.com/a-taste-from-the-new-angular-http-client-38fcdc6b359b

Angular更新了新的 4.3.0-rc.0 版本。在这个版本里,我们可以发现更新了我们一直期待的新功能 —— 一个革新了的HTTP Client API

HttpClient 是对现存的Angular HTTP API 一次进化,现有的HTTP API存在于一个单独的包中,即@angular/common/http。 这样的结构确保了已有的代码库可以慢慢更新到新的API而不至于出现断崖的更新

安装

首先,我们需要更新包版本到 4.3.0-rc.0 版本。 接下来,我们需要把 HttpClientModule 引入到我们的 AppModule

\\http-init.tsimport { HttpClientModule } from '@angular/common/http';@NgModule({ declarations: [
   AppComponent
 ], imports: [
   BrowserModule,
   HttpClientModule
 ], bootstrap: [AppComponent]
})
export class AppModule { }

`

现在我们准备好了。让我们来看看三个令人期待的新功能


默认使用JSON

JSON 作为默认的数据格式而不再需要明确地写出来需要解析

我们再也不需要写下如下的代码

http.get(url).map(res => res.json()).subscribe(...)

现在我们只需要写下

http.get(url).subscribe(...)


拦截器(Interceptors)支持

拦截器 允许在 管道语法(pipeline)中注入中间件

\\request-interceptor.tsimport {
  HttpRequest,
  HttpHandler,
  HttpEvent
} from '@angular/common/http';@Injectable()class JWTInterceptor implements HttpInterceptor {

  constructor(private userService: UserService) {}

  intercept(req: HttpRequest, next: HttpHandler): Observable> {

    const JWT = `Bearer ${this.userService.getToken()}`;
    req = req.clone({      setHeaders: {        Authorization: JWT
      }
    });    return next.handle(req);
  }
}

`

如果我们想要注册一个新的拦截器,我们需要去实现(implements)这个 HttpInterceptor 接口(interface)。这个接口有一个方法我们必须要去实现 —— 即拦截器

这个拦截器方法将会给我们一个请求对象(the Request object)、HTTP处理器(the HTTP handler)并且返回一个HttpEvent 类型的可观察对象(observable)

请求和返回对象需要是不可改变的。因此,我们需要在返回之前提前拷贝一个原始请求

接下来,next.handle(req) 方法将会调用一个带上新请求的底层的XHR然后返回一个返回事件的事件流(stream)

\\interceptor-response.ts@Injectable()class JWTInterceptor implements HttpInterceptor {

  constructor(private router: Router) {}

  intercept(req: HttpRequest, next: HttpHandler): Observable> {    return next.handle(req).map((event: HttpEvent) => {      if (event instanceof HttpResponse) {        // do stuff with response if you want
      }
    }, (err: any) => {      if (err instanceof HttpErrorResponse {        if (err.status === 401) {           // JWT expired, go to login
        }
      }
    });
  }
}

`

拦截器也可以选择通过应用附加的 Rx 操作符来转换响应事件流对象,在next.handle()中返回。

最后我们需要去做的注册该拦截器,使用 HTTP_INTERCEPTORS 注册 multi Provider:

[ { provide: HTTP_INTERCEPTORS, useClass: JWTInterceptor, multi: true } ]


进度事件

进度事件可以既用于请求上传也可以用于返回的下载

\\http-progress.ts

import {
  HttpEventType,
  HttpClient,
  HttpRequest
} from '@angular/common/http';

http.request(new HttpRequest(  'POST',
  URL,
  body, 
  {
    reportProgress: true
  })).subscribe(event => {  if (event.type === HttpEventType.DownloadProgress) {    // {
    // loaded:11, // Number of bytes uploaded or downloaded.
    // total :11 // Total number of bytes to upload or download
    // }
  }  if (event.type === HttpEventType.UploadProgress) {    // {
    // loaded:11, // Number of bytes uploaded or downloaded.
    // total :11 // Total number of bytes to upload or download
    // }
  }  if (event.type === HttpEventType.Response) {
    console.log(event.body);
  }

})

```

如果我们想要获得上传、下载进度的提示信息,我们需要传 { reportProgress: true }HttpRequest对象

这里还有两个新的功能我们今天没有提到:

基于内部测试框架的 Post-request verificationflush 功能 类型化,同步响应体访问,包括对 JSON body类型的支持。

以上只是对新的HTTP API和它的新功能的概述,完整的代码可以看 angular/packages/common/http

译者注

应该在哪里注册拦截器呢?

\\app.module.ts@NgModule({ 
  imports: [ BrowserModule ], 
  providers: [ 
  { provide: HTTP_INTERCEPTORS, useClass: JWTInterceptor, multi:   true } 
],  declarations: [ AppComponent ], 
  bootstrap: [ AppComponent ] 
}) 
export class AppModule { }