Roy*_*mir 2 logging error-logging rxjs angular angular-httpclient
我正在使用Angular和rxjs 5.xx.对于每个http请求,我必须在集中的位置记录响应 - 如果成功或失败.
我面临的问题是在调用一个catch条款的情况下.
例如 :
callRemote() {
return this.http.get("http://aaa.dom")
.catch(f=>Rx.Observable.of(f))
.do(f => console.log("logging response both bad and ok..."))
}
Run Code Online (Sandbox Code Playgroud)
这是一个http失败的请求.但我必须调用do运算符,因为我需要记录它.但是,如果.catch调用a,.do则不会调用.这就是我这样做的原因:
.catch(f=>Rx.Observable.of(f))
Run Code Online (Sandbox Code Playgroud)
所以我基本上捕获错误并将其包装为新的observable并继续执行该.do功能.
到现在为止还挺好.
现在的问题是,最终,订阅时,我想知道请求是否失败或确定.
基本上这就是我订阅的方式:
this._http.callRemote().subscribe(
(x => console.log('OK')),
(x => console.log('ERROR')),
(() => console.log('COMPLETE'))
);
Run Code Online (Sandbox Code Playgroud)
问题是所有内容都被重定向到sucess回调函数.甚至失败.我明白为什么会发生这种情况 - 因为我catch作为新的Observables 包裹失败了.
题
包装错误是否可能转发error回调,而不是success回调?
正如评论中已经提到的那样,捕捉不应该首先吞下错误,这肯定是一个nogo.通过这样做,您只是阻止rxjs链中的错误信号.
最终你可以在catch中进行日志记录然后重新抛出,但这样只有日志副作用才有点过分.
最简单的选择是在运算符中使用错误回调 arguent do.
根据本教程页面,do运算符可以采用3个参数(回调fns),基本上与订阅签名匹配:
1s参数:下一个回调
第二个参数:错误回调
第三个参数:回调完成
所以你可以重构如下:
callRemote() {
return this.http.get("http://aaa.dom")
.do(
response => console.log("logging response both bad and ok..."),
error => console.log("Something exploded, call 911");
}
Run Code Online (Sandbox Code Playgroud)
所以基本上你可以将该操作附加到HttpClient基本代码中的每个调用.很整洁,不是吗?
等等!乍一看,这可能看起来很整洁,但在你想要的同一时刻,它会适得其反:
为什么?
你将基本上使用do()操作修补每个可能的后端调用.如果对该逻辑进行1次更改意味着在3个以上的位置更改代码,则会发生一些有问题的事情.
更好的方法
随着HttpClient的引入,又添加了另一个API:HttpInterceptor API.
基本上,您可以在一个点上拦截所有传出请求.
怎么样?如下:
第一步,创建一个可用于封装日志记录逻辑的可注入服务;
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { AuthService } from './auth/auth.service';
import { Observable } from 'rxjs/Observable';
import { tap } from 'rxjs/operators'; // fancy pipe-able operators
@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
tap(
response => console.log("Oh boy we got an answer"),
error => console.log("Something might be burning back there")
));
}
}
Run Code Online (Sandbox Code Playgroud)
第二步,LoggingInterceptor通过令牌提供角度,使角度意识到存在:
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NgModule, ClassProvider } from '@angular/core';
import { LoggingInterceptor } from '../some-place';
const LOGGING_INTERCEPTOR_PROVIDER: ClassProvider = {
provide: HTTP_INTERCEPTORS ,
useClass: LoggingInterceptor,
multi: true
};
@NgModule({
...
providers: [
LOGGING_INTERCEPTOR_PROVIDER
]
...
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
就是这样!现在,您可以以真正集中的方式记录所有传出请求,并在必要时使用这些日志执行其他一些很酷的操作.
| 归档时间: |
|
| 查看次数: |
4360 次 |
| 最近记录: |