从拦截器加载组件

时间:2018-01-23 06:38:39

标签: angularjs ionic-framework

我打算在中心点处理网络错误。所以我正在使用拦截器。现在我有一个挑战,假设我有响应(任何请求)的会话超时,我想将用户重定向到登录页面。     在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);
        }
      }
    })
  }
}

2 个答案:

答案 0 :(得分:1)

我会使用Observable和Subject这样做。

例如http://jasonwatmore.com/post/2016/12/01/angular-2-communicating-between-components-with-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”。他们仍然称同一个事件。