2017-08-17 157 views
1

我已經創建了自定義Http服務來覆蓋「請求」方法,該方法在每個請求上更新令牌(如果需要的話)。但問題是我收到「循環依賴」錯誤。任何想法如何解決?Angular2中的自定義Http服務。循環依賴錯誤

定義HTTP服務:

import { Injectable } from '@angular/core'; 
import { 
    Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/http'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/catch'; 
import 'rxjs/add/observable/throw'; 
import {UserService} from "../services/user.service"; 

@Injectable() 
export class VodHttpService extends Http { 

    constructor(backend: XHRBackend, defaultOptions: RequestOptions, private userService : UserService) { 

     super(backend, defaultOptions); 
    } 

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> { 

     //adding access token to each http request before calling super(..,..) 
     let token = this.userService.token; 
     if (typeof url === 'string') { 
      if (!options) { 
       options = { headers: new Headers() }; 
      } 

      if (url != this.userService.PUBLIC_TOKEN_URL) { 
       options.headers.set('Authorization', `Bearer ${token}`); 
      } 
     } 
     else { 

      if (url.url != this.userService.PUBLIC_TOKEN_URL) { 
       url.headers.set('Authorization', `Bearer ${token}`); 
      } 
     } 

     console.log(url); 

     return super.request(url, options) 
      .catch((error) => { 
       //if got authorization error - try to update access token 
       if (error.status = 401) { 
        return this.userService.updateToken() 
         .flatMap((result: boolean) => { 
          //if got new access token - retry request 
          if (result) { 
           return this.request(url, options); 
          } 
          //otherwise - throw error 
          else { 
           return Observable.throw(new Error('Can\'t refresh the token')); 
          } 

         }) 
       } 
       else { 
        Observable.throw(error); 
       } 
      }) 

    } 

} 

我的單身用戶的服務期待這樣的:

import {Component, Injectable, Injector} from '@angular/core'; 
import {Http} from "@angular/http"; 
import {Observable} from "rxjs"; 
import {environment} from "../../environments/environment"; 

@Injectable() 
export class UserService { 

    public token : string; 
    public PUBLIC_TOKEN_URL = environment.token_url; 

    constructor (private _http: Http) { } 

    updateToken() : Observable<boolean> { 

     let url = this.PUBLIC_TOKEN_URL; 

     return this._http.get(url).map(res => { 

      // return res.json(); 
      if (typeof res.json().access_token !== 'undefined'){ 

       this.token = res.json().access_token; 
       return true; 
      } else { 

       return false; 
      } 
     }); 
    } 

} 

我知道哪裏是方式使用注射器來解決它,但我認爲這是醜陋的方法。

+1

您將'UserService'注入到一個對我來說不正確的http服務中。 – lexith

+0

正確的方法是溝通Http,使用替換它的新HttpClient,並編寫攔截器。 –

+0

您是否也可以在提供商註冊這2項服務的地方發佈代碼? (我假定這將是在模塊定義) –

回答

1

您的自定義VodHttpService的提供者定義不正確。它應該是這樣的:

export function vodHttpFactory(backend: XHRBackend, options: RequestOptions, userService: UserService) { 
     return new VodHttpService(backend, options, userService); 
    } 

@NgModule({ 
// other stuff 
providers: [ 
    UserService, 
    { 
     provide: VodHttpService, 
     useFactory: vodHttpFactory, 
     deps: [XHRBackend, RequestOptions, UserService] 
    } 
    ] 
}) 

注意,vodHttpFactory功能上是這樣寫的是要與AOT兼容的,如果你需要它。

+0

它的工作,感謝安德烈! – Alex91ckua