这一次,放下 axios,使用基于 rxjs 的响应式 HTTP 客户端
众所周知,在浏览器端和 Node.js 端使用最广泛的 HTTP 客户端为 axios 。想必大家都对它很熟悉,它是一个用于浏览器和 Node.js 的、基于 Promise 的 HTTP 客户端,但这次的主角不是它。
起源axios 的前身其实是 AngularJS 的 $http 服务。
为了避免混淆,这里需要澄清一下:AngularJS 并不等于 Angular,AngularJS 是特指 angular.js v1.x 版本,而 Angular 特指 angular v2+ (没有 .js)和其包含的一系列工具链。
这样说可能不太严谨,但 axios 深受 AngularJS 中提供的$http 服务的启发。归根结底,axios 是为了提供一个类似独立的服务,以便在 AngularJS 之外使用。
发展但在 Angular 中,却没有继续沿用之前的 $http 服务,而是选择与 rxjs 深度结合,设计出了一个比 $http 服务更先进的、现代化的,响应式的 HTTP 客户端。在这个响应式的 HTTP Client 中,发送请求后接收到的不再是一个 Promise ,而是来自 rxjs 的 Observable,我们可以订阅它,从而侦听到请求的响应:
constobservable=http.get('url');
observable.subscribe(o=console.log(o));
有关它的基本形态及详细用法,请参考官方文档。
正文@ngify/http 是一个形如 Angular HttpClient 的响应式 HTTP 客户端。@ngify/http的目标与 axios 相似:提供一个类似独立的服务,以便在 Angular 之外使用。
@ngify/http 提供了以下主要功能:
请求类型化响应对象的能力。简化的错误处理。请求和响应的拦截机制。默认支持但不限于 XMLHttpRequest 、Fetch API 与 微信小程序。先决条件在使用 @ngify/http 之前,您应该对以下内容有基本的了解:
JavaScript / TypeScript 编程。HTTP 协议的用法。RxJS Observable 相关技术和操作符。请参阅 Observables 指南。API有关完整的 API 定义,请访问 https://ngify.github.io/ngify.
可靠性@ngify/http 使用且通过了 Angular HttpClient 的单元测试(测试代码根据 API 的细微差异做出了相应的更改)。
安装npmi@ngify/http
基本用法import{HttpClient,HttpContext,HttpContextToken,HttpHeaders,HttpParams}from'@ngify/http';
import{filter}from'rxjs';
consthttp=newHttpClient();
http.get{code:number,data:any,msg:string}('url','k=v').pipe(
filter(({code})=code===0)
).subscribe(res=console.log(res));
http.post('url',{k:'v'}).subscribe(res=console.log(res));
constHTTP_CACHE_TOKEN=newHttpContextToken(()=1800000);
http.put('url',null,{
context:newHttpContext().set(HTTP_CACHE_TOKEN)
}).subscribe(res=console.log(res));
http.patch('url',null,{
params:{k:'v'}
}).subscribe(res=console.log(res));
http.delete('url',newHttpParams('k=v'),{
headers:newHttpHeaders({Authorization:'token'})
}).subscribe(res=console.log(res));
拦截请求和响应借助拦截机制,你可以声明一些拦截器,它们可以检查并转换从应用中发给服务器的 HTTP 请求。这些拦截器还可以在返回应用的途中检查和转换来自服务器的响应。多个拦截器构成了请求/响应处理器的双向链表。
@ngify/http 会按照您提供拦截器的顺序应用它们。
import{HttpClient,HttpHandler,HttpRequest,HttpEvent,HttpInterceptor}from'@ngify/http';
import{Observable,map}from'rxjs';
consthttp=newHttpClient([
newclassimplementsHttpInterceptor{
intercept(request:HttpRequestunknown,next:HttpHandler):ObservableHttpEventunknown{
//克隆请求以修改请求参数
request=request.clone({
headers:request.headers.set('Authorization','token')
returnnext.handle(request);
}
},
{
intercept(request:HttpRequestunknown,next:HttpHandler){
request=request.clone({
params:request.params.set('k','v')
console.log('拦截后的请求',request);
returnnext.handle(request).pipe(
tap(response=console.log('拦截后的响应',response))
}
}
]);
虽然拦截器有能力改变请求和响应,但 HttpRequest 和 HttpResponse 实例的属性是只读的,因此让它们基本上是不可变的。
有充足的理由把它们做成不可变对象:应用可能会重试发送很多次请求之后才能成功,这就意味着这个拦截器链表可能会多次重复处理同一个请求。如果拦截器可以修改原始的请求对象,那么重试阶段的操作就会从修改过的请求开始,而不是原始请求。而这种不可变性,可以确保这些拦截器在每次重试时看到的都是同样的原始请求。
如果你需要修改一个请求,请先将它克隆一份,修改这个克隆体后再把它传递给 next.handle()。
替换 HTTP 请求类@ngify/http 内置了以下 HTTP 请求类:
HTTP 请求类描述HttpXhrBackend使用 XMLHttpRequest 进行 HTTP 请求HttpFetchBackend使用 Fetch API 进行 HTTP 请求HttpWxBackend在 微信小程序 中进行 HTTP 请求默认使用 HttpXhrBackend,可以通过修改配置切换到其他的 HTTP 请求类:
import{HttpFetchBackend,HttpWxBackend,setupConfig}from'@ngify/http';
setupConfig({
backend:newHttpFetchBackend()
});
你还可使用自定义的 HttpBackend 实现类:
import{HttpBackend,HttpClient,HttpRequest,HttpEvent,setupConfig}from'@ngify/http';
import{Observable}from'rxjs';
//需要实现HttpBackend接口
classCustomHttpBackendimplementsHttpBackend{
handle(request:HttpRequestany):ObservableHttpEventany{
//...
}
}
setupConfig({
backend:newCustomHttpBackend()
});
如果需要为某个 HttpClient 单独配置 HttpBackend,可以在 HttpClient 构造方法的第二个参数传入:
consthttp=newHttpClient(null,newCustomHttpBackend())
在 Node.js 中使用@ngify/http 默认使用浏览器实现的 XMLHttpRequest 与 Fetch API。要在 Node.js 中使用,您需要进行以下步骤:
XMLHttpRequest如果需要在 Node.js 环境下使用 XMLHttpRequest,可以使用 xhr2,它在 Node.js API 上实现了 W3C XMLHttpRequest 规范。
要使用 xhr2 ,您需要创建一个返回 XMLHttpRequest 实例的工厂函数,并将其作为参数传递给 HttpXhrBackend 构造函数:
import{HttpXhrBackend,setupConfig}from'@ngify/http';
import*asxhr2from'xhr2';
setupConfig({
backend:newHttpXhrBackend(()=newxhr2.XMLHttpRequest())
});
Fetch API如果需要在 Node.js 环境下使用 Fetch API,可以使用 node-fetch 和 abort-controller。
要应用它们,您需要分别将它们添加到 Node.js 的 global:
importfetchfrom'node-fetch';
importAbortControllerfrom'abort-controller';
import{HttpFetchBackend,HttpWxBackend,setupConfig}from'@ngify/http';
global.fetch=fetch;
global.AbortController=AbortController;
setupConfig({
backend:newHttpFetchBackend()
});
传递额外参数为保持 API 的统一,需要借助 HttpContext 来传递一些额外参数。
Fetch API 额外参数import{HttpContext,FETCH_TOKEN}from'@ngify/http';
//...
//FetchAPI允许跨域请求
http.get('url',null,{
context:newHttpContext().set(FETCH_TOKEN,{
mode:'cors',
//...
})
});
微信小程序额外参数import{HttpContext,WX_UPLOAD_FILE_TOKEN,WX_DOWNLOAD_FILE_TOKEN,WX_REQUSET_TOKEN}from'@ngify/http';
//...
//微信小程序开启HTTP2
http.get('url',null,{
context:newHttpContext().set(WX_REQUSET_TOKEN,{
enableHttp2:true,
})
});
//微信小程序文件上传
http.post('url',null,{
context:newHttpContext().set(WX_UPLOAD_FILE_TOKEN,{
filePath:'filePath',
fileName:'fileName'
})
});
//微信小程序文件下载
http.get('url',null,{
context:newHttpContext().set(WX_DOWNLOAD_FILE_TOKEN,{
filePath:'filePath'
})
});
更多有关更多用法,请访问 https://angular.cn。
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线