我正在构建一个角度为5的应用程序,其中有2个拦截器:
我希望第二个拦截器仅在错误不是504或者它是504并且已经被第一个拦截器重试时被调用。
我创建了一个包含两个拦截器的示例:https://stackblitz.com/edit/angular-interceptors-ckbvsb
希望得到一些帮助!
由于
更新:
感谢大家的帮助!我最终以这样的方式实现它:
@Injectable()
export class I1 implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('intercepted I1');
return next.handle(req)
.retryWhen(error => {
return error
.mergeMap((err, i) => {
if (i > 0) return Observable.throw(err)
if (err instanceof HttpErrorResponse && err.status === 504) { // timeout
return Observable.of(err).delay(5000);
} else {
return Observable.throw({ error: 'No retry', cause: err })
}
})
});
}
}
答案 0 :(得分:3)
您的问题是您提供两个拦截器的顺序。你首先提供I1然后提供I2。这意味着请求将流经I1→I2,但响应将流经I2,然后流经I1。所以只需切换顺序:
@NgModule({
imports: [BrowserModule, HttpClientModule],
declarations: [AppComponent],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: I2, // <-- I2 first
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: I1, // <-- And only then I1
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
答案 1 :(得分:2)
以下是一种如何完成的方法 - 将其应用于您的代码:
// an observable producer that produces an error
const producer = (obs) => {
obs.next(0);
obs.error(new Error('504'));
};
const i1 = Observable.create(producer).pipe(
retryWhen((errors) => {
return errors.pipe(
scan((a, v, i) => {
a.unshift(v);
return a;
}, []),
map((v) => {
if (!v[0].message.includes('504') || v.length > 1) {
throw v[0];
} else {
return v[0].message;
}
}),
delay(2000)
)
})
);
答案 2 :(得分:-1)
我不确定这是处理这类事情的正确方法,拦截器用于检查请求,而不是响应,他们不关心返回的响应,因为您在查看响应之前使用.next传递请求。
似乎更适合在检查响应的服务中完成,然后对另一个资源执行另一个请求。
保留重试拦截器并检查您对服务本身或组件的响应以使用回退URL。