我打算在中心点处理网络错误。所以我正在使用拦截器。现在我有一个挑战,假设我有响应(任何请求)的会话超时,我想将用户重定向到登录页面。 在Ionic NavController中是加载任何组件(页面)的解决方案。 如何使用此NavController在Interceptor中加载页面/组件。
Here is my interceptor:
export class PostInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next:HttpHandler):Observable<HttpEvent<any>>
{
let postReq = req.clone();
let authenticationToken = localStorage.getItem('token');
postReq.headers.set('Content-Type','application/json');
if(authenticationToken != null) {
postReq.headers.append('Bearer',authenticationToken);
}
return next.handle(postReq).do(event => {
if (event instanceof HttpResponse) {
/*const time = new Date().toLocaleString();
console.log(`Request happened at ${time}.`);*/
if(event.body.loggedIn != null) {
//loggedIn = false
if(!event.body.loggedIn) {
}
else {
//Do Nothing
console.log('LoggedIn True')
}
}
else {
console.log(event.body);
AppModule.map.set('prevRequest',postReq);
}
}
})
}
}
答案 0 :(得分:1)
我会使用Observable和Subject这样做。
适用于您的案件:
首先创建服务:
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class MyService {
private requestInterceptedSource: Subject<number> = new Subject<number>();
requestIntercepted: Observable<number> = this.requestInterceptedSource.asObservable();
constructor() {
}
getInterceptedSource(): Subject<number> {
return this.requestInterceptedSource;
}
}
然后在拦截器中使用此服务以传播错误:
export class PostInterceptor implements HttpInterceptor {
constructor(private myService: MyService) {}
intercept(req: HttpRequest<any>, next:HttpHandler):Observable<HttpEvent<any>>
{
// I didn't copy/pasted your code...of course you should still use it ;)
// Here we start to propagate the error
this.myService.getInterceptedSource().next(err.status);
}
}
最后在你的app.component.ts
中观看(订阅)主题,以便在出现错误时重定向(我会说setRoot,因为出现了错误):
private subscription: Subscription;
constructor(private app: App, private myService: MyService) {
this.subscription = this.myService.requestIntercepted.subscribe((errorCode: number) => {this.app.getRootNav().setRoot('YourPage'});
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
答案 1 :(得分:1)
我最终使用内置的事件来处理重定向和超时。我有一个用于呼出电话的HTTP拦截器和一个响应拦截器,如下面的第二个片段所示。仅显示此帖子的响应拦截器。这是我创建的无耻博客文章:
Ionic: Handle 401 & 408 HTTP Responses in Interceptor
首先在app.component中,您需要订阅要创建的事件。如下所述,在未经授权的情况下,我删除身份验证,然后将根目录设置为我的登录页面。我还显示了一个弹出窗口。超时后,我只会显示一个弹出窗口。
this.events.subscribe("unauthorized:requestError",
() => {
this.authenticationService.removeAuthentication()
.then(() => {
this.nav.setRoot(LoginPage);
const alert = this.alertCtrl.create({
title: "Unauthorized",
subTitle: "Your credentials have expired. Please log back in.",
buttons: ["OK"]
});
alert.present();
});
});
this.events.subscribe("timeout:requestError",
() => {
const alert = this.alertCtrl.create({
title: "Request Timeout",
subTitle: "Please refresh or try your request again.",
buttons: ["OK"]
});
alert.present();
});
接下来,在拦截器中,我将使用Ionic Angular中的事件在需要时发布它们。您将需要导入它们,然后将它们注入到构造函数中。
import { Injectable } from "@angular/core";
import { Events } from "ionic-angular";
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpResponse, HttpErrorResponse } from "@angular/common/http";
import { Observable } from "rxjs/Observable";
@Injectable()
export class ResponseInterceptor implements HttpInterceptor {
constructor(
public events: Events
){}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff with response if you want
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
this.events.publish("unauthorized:requestError");
} else if (err.status === 408) {
this.events.publish("timeout:requestError");
}
} else if (err.name === "TimeoutError") {
this.events.publish("timeout:requestError");
}
});
}
}
我会从上面说我的超时,这是我在传出拦截器中等待15秒后拒绝呼叫的时间。那是err.name ===“ TimeoutError”。他们仍然称同一个事件。