2016-06-30 15 views
1

Ich versuche gerade, eine benutzerdefinierte XHRBackend für meine angular2 App zu erstellen. Ich möchte alle HTTP-Antworten mit einem HTTP-Antwortcode 401 (nicht autorisiert) abfangen, um den Benutzer auf der Anmeldeseite umzuleiten. Aber hier kommt mein Problem: der DI ist nicht in der Lage, die Router in meinem Custom-Backend zu laden.Dependency Injection lädt nicht alle Parameter

@Injectable() 
export class CustomXHRBackend extends XHRBackend { 
    constructor(
     _browserXHR: BrowserXhr, 
     _baseResponseOptions: ResponseOptions, 
     _xsrfStrategy: XSRFStrategy, 
     private router : Router) { 
     super(_browserXHR, _baseResponseOptions, _xsrfStrategy); 
     console.log(router); // --> undefined 
    } 

    createConnection(request: Request) { 
     let xhrConnection = super.createConnection(request); 
     xhrConnection.response = xhrConnection.response.catch((error, caugth) => { 
      if(error.status === 401) { 
       //Do stuff with the new router 
       this.router.navigate(['/login']); 
      } 
      return Observable.throw(caugth); 
     }); 
     return xhrConnection; 
    } 
} 

Es scheint, wie immer noch die DI die Metadaten des XHRBackend verwendet, weil die ersten 3 params definiert sind.


habe ich eine plunkr, das dieses Problem veranschaulicht: http://plnkr.co/edit/44imf9KpE06cIyQ395sg?p=preview

Hinweis:

Die plunkr basiert auf dem angular2 Router Beispiel, leider hatte ich nicht genug Zeit, um einen kleineren zu schaffen ein. Die wichtigen Dateien sind custom.backend.ts und vielleicht main.ts.


Hat jemand eine Idee, warum das passiert?

Antwort

2

Dafür würde ich stattdessen die Http Klasse erweitern. Hier ist ein Beispiel:

@Injectable() 
export class CustomHttp extends Http { 
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) { 
    super(backend, defaultOptions); 
    } 

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> { 
    console.log('request...'); 
    return super.request(url, options).catch(res => { 
     // do something 
    });   
    } 

    get(url: string, options?: RequestOptionsArgs): Observable<Response> { 
    console.log('get...'); 
    return super.get(url, options).catch(res => { 
     // do something 
    }); 
    } 
} 

und registrieren Sie es, wie unten beschrieben:

bootstrap(AppComponent, [HTTP_PROVIDERS, 
    new Provider(Http, { 
     useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions), 
     deps: [XHRBackend, RequestOptions] 
    }) 
]); 

bearbeiten

Ich glaube, Sie müssen explizit bieten Parametern useFactory:

import {provide} from '@angular/core'; 
import {Router} from '@angular/router'; 
import { bootstrap }   from '@angular/platform-browser-dynamic'; 
import { AppComponent }   from './app.component'; 
import { APP_ROUTER_PROVIDERS } from './app.routes'; 
import {HTTP_PROVIDERS, Http,RequestOptions, XHRBackend, XSRFStrategy, BrowserXhr} from '@angular/http'; 
import {CustomXHRBackend} from './custom.backend'; 

bootstrap(AppComponent, [ 
    APP_ROUTER_PROVIDERS, 
    HTTP_PROVIDERS, 
    provide(XHRBackend, { 
    useFactory: (browserXHR: BrowserXhr, requestOptions: RequestOptions, xsrfStrategy: XSRFStrategy, router: Router) => { 
     return new CustomXHRBackend(browserXHR, requestOptions, xsrfStrategy, router); 
    }, 
    deps: [BrowserXhr, RequestOptions, XSRFStrategy, Router] 
    }) 
]); 

Siehe dieses Plunkr: http://plnkr.co/edit/JK3q5nspZ434AeJJsUeJ?p=preview.

+0

Aber dann müsste ich das mit jeder 'HTTP-Methode' machen. Denkst du nicht, es wäre besser, es nur einmal zu tun? Wir werden nur das XHRBackend verwenden. – Dinistro

+0

Und das behebt das Problem nicht, dass ich nicht in der Lage bin, etwas anderes als die 3 Parameter in ein benutzerdefiniertes Backend zu injizieren. – Dinistro

+1

Für die Injektion Problem, ich denke, Sie müssen explizite Parameter mit 'UseFactory' bereitstellen. Ich habe meine Antwort aktualisiert. –