2016-03-25 4 views
14

少し助けてもらえますか?私はcatchObservableを使ったとき、ちょっと混乱しているようです。Angular2- Observableと混乱する閉鎖範囲をキャッチ

私のAPIが403エラーを返すとき、TokenStoreでいくつかのアクションを実行したい、つまりローカルトークンを削除し、そのユーザーをunauthenticatedとしてマークします。私がこれをやろうとしている方法が間違っているかもしれないので、これを達成するより良い方法があれば私に知らせてください。

私は次のコードでこれを実現しようとしている:

APIConnector.service.ts - APIの通信方式のための単一のサービスを使用私のサービスのそれぞれにおいて

import {Injectable} from 'angular2/core'; 
import {Http, Response, Headers, RequestOptions} from 'angular2/http'; 
import {Observable}  from 'rxjs/Observable'; 
import * as _ from 'lodash'; 
import {Logger}  from './logger.service'; 
import {TokenStore} from '../stores/token.store'; 

@Injectable() 
export class APIConnector { 

    private _apiUrl:string = 'https://api.sb.zerojargon.com/'; 
    private _token:string = null; 

    constructor(
     private _http:Http, 
     private _logger:Logger, 
     private _tokenStore:TokenStore 
    ) {} 

    get(endpoint:String, includes:Array<string>) { 
     let includeString = (!_.isUndefined(includes)) ? this._parseIncludes(includes) : ''; 
     let headers = this._createHeaders(); 
     let options = new RequestOptions({ headers: headers }); 
     return this._http.get(this._apiUrl + endpoint + '?include=' + includeString, options); 
    } 

    post(endpoint:String, formData:Object, includes:Array<string>) { 
     let includeString = (!_.isUndefined(includes)) ? this._parseIncludes(includes) : ''; 
     let body = JSON.stringify(formData); 
     let headers = this._createHeaders(); 
     let options = new RequestOptions({ headers: headers }); 
     return this._http.post(this._apiUrl + endpoint + '?include=' + includeString, body, options); 
    } 

    handleError(error: Response) { 
     // log out the user if we get a 401 message 
     if (error.json().error.http_code === 401) { 
      this._tokenStore.destroy(); 
     } 
     return Observable.throw(error.json().error || 'Server error'); 
    } 

    private _parseIncludes(includes:Array<String>) { 
     return includes.join(); 
    } 

    private _createHeaders() { 
     return new Headers({ 'Content-Type': 'application/json', 'Authorization': 'bearer ' + localStorage.getItem('token') }); 
    } 
} 

APIConnector、私はObservableのメソッドをキャッチして、handleErrorクロージャを実行します。例えば

public createEvent(event:Object) { 
    let endpoint = this._endpoint; 
    return this._apiConnector.post('clients/'+this.client+'/events', event, this._defaultIncludes) 
     .map(res => { 
      return this._transformer.map('event', <Object[]>res.json()); 
     }) 
     .catch(this._apiConnector.handleError); 
} 

しかし、これは次のエラーを与える:handleErrorのはクロージャであるため、

EXCEPTION: TypeError: Cannot read property 'destroy' of undefined

は、おそらくこれがあります。私はこれに対処する最善の方法が不明です。

任意の考えを大幅問題は、あなたがそのコンテキストを失うので、あなたは関数を直接参照することをある

+2

あなたがしなければ '.catch(エラー=> this._apiConnector.handleError(エラー)) '? – Abdulrahman

答えて

21

をいただければ幸いです。私はそれが今や機能と方法であることを意味します。

この修正する2つの方法があります。

  • はこれに結合機能を:

    .catch(this._apiConnector.handleError.bind(this)); 
    

    あなたがここに種類を失うことになるので、このアプローチは推奨されませんが。詳細については、このリンクを参照してください:https://basarat.gitbooks.io/typescript/content/docs/tips/bind.html

  • 矢印関数に呼び出しをラップ:

    .catch((error) => { 
        this._apiConnector.handleError(error); 
    }); 
    
+4

この回答は、1つの小さな調整で正しいものでした。 catchメソッドは何かを返す必要があるので、大括弧内に 'return'が必要です。 – user43138

+2

新しいエラーまたは同じエラーをスローしたい場合は、「return Observable.throw(error);」を返します。それがあなたの事件でないなら、戻らないでください。エラーは、別のキャッチまたはサブスクライブの2番目のコールバックに伝播されません。 –

+2

私は同じ問題を抱えていて、この答えはそれを解決しました。しかし、私は括弧なしのソリューションが好きで、 '_apiConnector'の方がずっといい。 '.catch(error => this.handleError(error));' – hogan

関連する問題