一、原Http使用总结

使用方法

  1. 在根模块或核心模块引入HttpModule

    即在AppModule或CoreModule中引入HttpModule:
import { HttpModule } from '@angular/http';
@NgModule({
import: [ HttpModule ]
// ...
})
AppModule {}
  1. 在使用的地方注入Http服务
import { Http } from '@angular/http';
// ...
constructor(
private http: Http
) {}
ngOnInit() {
this.http.get(`url`).subscribe((res) => {
// 成功回调
}, (err) => {
// 失败回调
});
}
// ...
  1. 使用可选参数

    若想在请求中添加特定的头部或者身体,就需要配置请求的可选参数:
import { Http, Header } from '@angular/http';
// ...
this.http.delete(`url`, {headers: new Header(), body: { } }).subscribe(...);
// ...

缺陷

  • 已知缺陷之一为不支持文件传输,如果想要写一个文件上传的客户端,就只能使用JS原生的XMLHttpRequest对象,然后自己封装上rxjs得到一个较通用的文件上传服务,可以参考 ngx-uploader
  • 另一个不能算缺陷的缺陷是Http请求得到的响应结果必须手动执行json()以得到json格式的结果。

二、改用HttpClient

HttpClient能力在angular 4.3版本开始引入在@angular/common/http中

使用方法

基本使用方法与原Http服务类似,先引入HttpClientModule,然后注入HttpClient服务使用:

import { HttpClientModule } from '@angular/common/http';
// ...
@NgModule({
import: [ HttpClientModule ]
})
// ...
import { HttpClient } from '@angular/common/http';
// ...
constructor(
private http: HttpClient
) {}
// ...
this.http.get('url').subscribe((res) => {
// 成功回调
}, (err) => {
// 失败回调
});
// ...

添加额外头部等信息的话类似原Http服务,引入相关的变量后填入第二个可选参数即可。

改进与加强

  1. 支持更多类型的请求,比如更改可选参数的responseType值可改为直接请求text内容
  2. 不再需要手动调用json()来将结果转为json格式,订阅到的结果已经是body且转为了json(请求text的话直接就是text内容)。
  3. 支持监听请求进度(可用于文件上传)。
  4. 添加了拦截器能力,用于预设请求规则和响应预处理。

缺陷

已知的一个小缺陷是,delete请求不能再添加body作为可选参数了,这个略尴尬,难道批量删除也得乖乖把参数拼到url中。。。

三、拦截器

本文暂不讨论文件上传以及请求进度的监听能力,可以查看官网的相关内容,本文主要来讲拦截器的简单使用。

给应用注入拦截器的效果是,所有的HttpClient发起的请求都将执行这个拦截器,类似Node中的中间件。

且无论是请求之前的预处理还是得到响应后的预处理都能做到。

笔者想到的第一个用处就是不再需要写一个自己的Http服务来代执行angular的Http服务了,以往如果想要给应用的所有请求都添加比如认证功能的请求头的话,比较好的办法就是自己建立一个MyHttp服务来代为调用Http方法,并在请求回调中添加统一的结果处理。

拦截器属于特殊服务,实现了HttpInterceptor类:

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http'; @Injectable()
export class MyInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req);
}
}

编辑好拦截器后需要注入到根模块中:

import {NgModule} from '@angular/core';
import {HTTP_INTERCEPTORS} from '@angular/common/http'; @NgModule({
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: MyInterceptor,
multi: true,
}],
})
export class AppModule {}

预处理请求

所有工作都在拦截器中的intercept方法中进行,如果要给所有请求加一个认证头部,可以操作其中的req参数,注意req参数为只读的,必须执行其clone方法得到副本来操作,处理完的副本通过next参数发射出去即可:

public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let authInfo = {token: 'testtoken', admin: 'testadmin'};
const authReq = req.clone({
headers: req.headers
.set('Authorization', authInfo.token || '')
.set('Admin', authInfo.admin || '')
.set('Content-Type', 'application/json;charset=UTF-8')
});
return next.handle(authReq);
}

这样实际使用请求时可以直接使用HttpClient,所有请求都会实现添加配置好的头部信息。

响应预处理

请求得到结果后,往往需要对结果进行一些判断,比如某些错误是请求本身的错误,这些错误会直接抛出到rxjs的error流中,某些请求本身是成功的,但是是属于一些服务器逻辑给出的错误,这类错误如果不做处理是会被认为是成功的请求而直接next到成功回调的,这会导致最终订阅请求时,错误的回调要做错误处理,成功回调中也存在需要做错误处理,感觉成功还得分为成功地成功和成功地失败,很尴尬:

someReq().subscribe((res) => {
if (res.state) {
// 真正成功
} else {
// 还是失败
}
}, (err) => {
// 失败
});

通过拦截器可以对请求结果进行重新整理,保证成功回调必然成功,失败回调必然失败:

return next.handle(authReq).map((event) => {
if (event instanceof HttpResponse) {
switch (event.status) {
case 200:
if (event.body['state']) {
let newEvent = event.clone({body: event.body['data']});
return newEvent;
} else {
throw event.body['msg'];
}
case 401:
this.storage.remove('auth_token');
this.router.navigate(['/login']);
default:
throw `【${event.status}】【${event.statusText}】`;
}
}
return event;
});

响应预处理的一句话总结就是操作intercept方法返回的next.handle(req),使用rxjs的map操作符进行映射。

四、搭配rxjs

rxjs是angular严重依赖的一个大坑,初次接触会被其创建和订阅这种使用方式搭配一大堆眼花缭乱的操作符弄得一脸懵逼。

创建-订阅的请求方式

原Http和新的HttpClient两个服务流严重依赖了rxjs,请求的发起返回的是一个Observable对象,其定义好后并不会直接发起请求,真正发起请求是在执行其subscribe方法的时候,此方法接收三个参数,分别是成功回调、失败回调和完成回调。

  • Promise的套路是请求在定义(调用)的时候就发起了,然后迎来的是一连串的then()和catch()。可以从catch中resolve到then,或者从then中reject到catch。
  • rxjs的套路则是先创建出一个观察者对象(Observable),可以用许多操作符定义许多规则,比如个人感觉很接近then的map操作符,以及接近catch的catch操作符。可以从map操作符中直接throw到错误回调,或者在catch操作符中捕捉错误并返回新的成功的流。这一切都不会触发这个请求,只有最终subscribe()的时候,才会真正执行整个请求,并在三种回调中体现。

对于rxjs的学习强烈推荐 Rxjs 5 ultimate 简直胜看十篇博。

使用angular的HttpClient搭配rxjs的更多相关文章

  1. [Angular + Unit Testing] Mock HTTP Requests made with Angular’s HttpClient in Unit Tests

    In a proper unit test we want to isolate external dependencies as much as possible to guarantee a re ...

  2. Angular基础(八) Observable & RxJS

    对于一个应用来说,获取数据的方法可以有很多,比如:Ajax, Websockets, LocalStorage, Indexdb, Service Workers,但是如何整合多种数据源.如何避免BU ...

  3. Angular 4+ HttpClient

    个人博客迁移至 http://www.sulishibaobei.com  处: 这篇,算是上一篇Angular 4+ Http的后续: Angular 4.3.0-rc.0 版本已经发布

  4. angular 项目中遇到rxjs error TS1005:';'

    因为rxjs的版本问题,只需要在package.json 中将依赖的 rxjs:'^6.00' 改为 rxjs'6.00', 然后执行 npm update 更新下rxjs的依赖版本即可解决

  5. Angular快速学习笔记(4) -- Observable与RxJS

    介绍RxJS前,先介绍Observable 可观察对象(Observable) 可观察对象支持在应用中的发布者和订阅者之间传递消息. 可观察对象可以发送多个任意类型的值 -- 字面量.消息.事件. 基 ...

  6. [Angular2 Form] Use RxJS Streams with Angular 2 Forms

    Angular 2 forms provide RxJS streams for you to work with the data and validity as it flows out of t ...

  7. Angular:在应用初始化时运行代码

    想象一下,您的应用需要一些动态配置信息,这些信息在应用启动之前需要动态获取,并在应用运行中使用. 显然不能直接写道静态配置文件中,但是从客户端发出的请求又是一个异步请求,如何协调这个问题呢? 这里,我 ...

  8. RxJS v6 学习指南

    为什么要使用 RxJS RxJS 是一套处理异步编程的 API,那么我将从异步讲起. 前端编程中的异步有:事件(event).AJAX.动画(animation).定时器(timer). 异步常见的问 ...

  9. 使用ASP.NET Web API和Web API Client Gen使Angular 2应用程序的开发更加高效

    本文介绍“ 为ASP.NET Web API生成TypeScript客户端API ”,重点介绍Angular 2+代码示例和各自的SDLC.如果您正在开发.NET Core Web API后端,则可能 ...

随机推荐

  1. hdu_3746: Cyclic Nacklace

    题目链接 给出一个字符串,你可以通过在首尾加入字符使其变成一个具有周期T(T>=2)的字符串,求所需加入的最少字符数. 所考察算法仍然是对next数组含义的理解 #include<cstd ...

  2. 文本三剑客---gawk基础

    gawk程序是Unix中原始awk程序的GNU版本.gawk程序让流编辑器迈上了一个新的台阶,它提供了一种编程语言而不只是编辑器命令.在gawk编程语言中,可以完成下面的事情: (1)定义变量来保存数 ...

  3. JavaScript Base64加解密

    Base64加密算法是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045-RFC2049,上面有MIME的详细规范.Base64编码可用于在HTTP环境下传递较长的标识信 ...

  4. 云游戏学习与实践(二)——安装GamingAnywhere

    安装GamingAnywhere 一.GamingAnywhere项目 GamingAnywhere是一个开源的实现云游戏的引擎,并且高效.跨平台.易扩展.可调配. GitHub地址:https:// ...

  5. Verilog HDL程序设计——基本要素

    Verilog基本上熟悉了,继续整理一下Verilog的学习笔记吧.前面记载了Verilog的结构,写Verilog的结构有了,但是该怎么写呢?在写之前就得了解一下Verilog的一些基本要素了,也就 ...

  6. Fiddler基础使用一之捕获https请求

    fiddler抓包工具: http协议cookieFiddler是一个调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的"进出"Fiddle ...

  7. Promise和异步编程

    前面的话 JS有很多强大的功能,其中一个是它可以轻松地搞定异步编程.作为一门为Web而生的语言,它从一开始就需要能够响应异步的用户交互,如点击和按键操作等.Node.js用回调函数代替了事件,使异步编 ...

  8. python中全局变量和局部变量的一个小坑

    python 中全局变量和局部变量在使用过程中的一个容易出错的地方 什么是全局变量 python中,在函数外部声明的变量可以叫做全局变量. x = 10 def fn1(): pass fn1() 什 ...

  9. 关于JavaScript组件化的探索

    Loaders 先放出项目地址:https://github.com/j20041426/Loaders 这是一个可以动态选择加载动画的样式和颜色的插件.这个项目仅仅是作为对js组件化的一个探索,不太 ...

  10. 花了一年时间开发的三维弯管机交互式转档软件(三维管子模型UG,SOLIDWORK,PRO/E文件转成YBC)

    在弯管机加工中,由管子模型生成可直接进行弯管加工的YBC数据可以大大提高弯管编程过程.传统的做法是先用dxf数据文件(用autocad绘制管子的轴心线数据)转出XYZ数据,然后由XYZ数据转成YBC数 ...