【问题标题】:Extend http on dont call request method in Angular 2在Angular 2中扩展http不调用请求方法
【发布时间】:2016-12-22 12:32:32
【问题描述】:

我是 Angular 2 的新手,我正在尝试使用 JWT 创建一个应用程序。因此,为此,我关注http://www.adonespitogo.com/articles/angular-2-extending-http-provider/ 的帖子。

但我是个问题,请求方法永远不会调用,登录后我必须刷新页面才能发送令牌。

这是我的课

http.service.ts

import { Injectable } from '@angular/core';
import { Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class HttpService extends Http {

  constructor (backend: XHRBackend, options: RequestOptions) {    
    let token = localStorage.getItem('auth_token'); // your custom token getter function here
    options.headers.set('Authorization', `Bearer ${token}`);
    options.headers.append('Content-Type', 'application/json');
    super(backend, options);
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    let token = localStorage.getItem('auth_token');
    if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
      if (!options) {
        // let's make option object
        options = {headers: new Headers()};
      }
      options.headers.set('Authorization', `Bearer ${token}`);
      options.headers.append('Content-Type', 'application/json');
    } else {
    // we have to add the token to the url object
      url.headers.set('Authorization', `Bearer ${token}`);
      url.headers.append('Content-Type', 'application/json');
    }
    return super.request(url, options)
                .catch(this.catchAuthError(this));
  }

  private catchAuthError (self: HttpService) {
    // we have to pass HttpService's own instance here as `self`
    return (res: Response) => {
      console.log(res);
      if (res.status === 401 || res.status === 403) {
        // if not authenticated
        console.log(res);
      }
      return Observable.throw(res);
    };
  }
}

app.module.ts

providers: [{
      provide: HttpService,
      useFactory: (backend: XHRBackend, options: RequestOptions) => {
        return new HttpService(backend, options);
      },
      deps: [XHRBackend, RequestOptions]
    }, LoggedInGuard, UserService],

picture.service.ts

@Injectable()
export class PictureService {

    url: string = 'v1/pictures';

    constructor(private http: HttpService) { }

    list(): Observable<PictureComponent[]> {
         return this.http
                    .get(this.url)
                    .map(res => res.json());
    }

}

使用picture.service.ts的组件

@Component({
    moduleId: module.id,
    selector: 'picture-list',
    templateUrl: './pictureList.component.html'
})
export class ListagemComponent { 

    pictures: PictureComponent[] = [];
    service: PictureService;
    msg: String = '';

    constructor(service: PictureService){
        this.service = service;
        this.service
            .list()
            .subscribe(pictures => {
                this.pictures = pictures;
            }, err => console.log(err));
    }

 }

感谢帮助

【问题讨论】:

  • 我看不出你的代码有什么问题。所有有角度的http方法都通过request方法,所以我认为它不可能不被调用。
  • @AdonesPitogo 我使用了 mrgoos 提到的覆盖并且工作得非常好。非常感谢

标签: http angular jwt


【解决方案1】:

您是否在模块中提供了picture.service?如果没有,您应该在您的@component 或您的模块中提供它,如果您希望在全局范围内提供它。

【讨论】:

    【解决方案2】:

    我扩展了 XHRBackend

    import { Injectable } from '@angular/core';
    import { Request, XHRBackend, BrowserXhr, ResponseOptions, XSRFStrategy, Response } from '@angular/http';
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/operator/catch';
    import 'rxjs/add/observable/throw';
    
    @Injectable()
    export class ExtendedXHRBackend extends XHRBackend {
    
      constructor(browserXhr: BrowserXhr, baseResponseOptions: ResponseOptions, xsrfStrategy: XSRFStrategy) {
        super(browserXhr, baseResponseOptions, xsrfStrategy);
      }
    
      createConnection(request: Request) {
        let token = localStorage.getItem('token');
        request.headers.set('x-access-token', `${token}`); 
        request.headers.set('Content-Type', 'application/json');
        let xhrConnection = super.createConnection(request);
        xhrConnection.response = xhrConnection.response.catch((error: Response) => {
          if (error.status === 401 || error.status === 403) {
            console.log('access not alowed');
            localStorage.removeItem('token');
          }
          return Observable.throw(error);
        });
        return xhrConnection;
      }
    }
    

    并在应用模块上使用

    providers: [{ provide: XHRBackend, useClass: ExtendedXHRBackend }]
    

    在这之后我解决了这个问题并且工作得很好

    【讨论】:

    • Vinicius,请记住,如果您扩展 XHRBackend,您将无法使用您的服务,因为它们由于角核心错误而无法正确继承,如 Adones 博客中所述。我刚刚在最新的 RC 版本中看到它正在修复:github.com/angular/angular/blob/master/…
    • 更新:在 Angular 2.3.0 中,您可以安全地覆盖 HTTP 类:{ provide: Http, useClass: ExtendedHttpService }
    • @mrgoos 覆盖 Adone 代码效果很好!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    相关资源
    最近更新 更多