2017-08-17 156 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