2016-03-25 2 views
14

Удивление, если вы можете немного помочь. Кажется, я немного запутался, когда дело дошло до использования catch с Observable.Угловая2- Путаница с наблюдаемой областью закрытия улова

В основном то, что я пытаюсь сделать, это следующий: Когда мой API возвращает ошибку 403, я хочу, чтобы выполнить какие-либо действия на моем TokenStore, а именно, удалить локальный маркер и отметьте пользователь как неаутентифицированные. То, как я пытаюсь это сделать, может быть неправильным, поэтому, пожалуйста, дайте мне знать, есть ли лучший способ добиться этого.

Я пытаюсь сделать это с помощью следующего кода:

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, у меня есть методы catch на Observable s, чтобы запустить закрытие 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); 
} 

Однако это дает следующее сообщение об ошибке:

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

Предположительно это происходит потому, HandleError является замыканием. Однако я не уверен в том, как лучше справиться с этим.

Все мысли были бы весьма признателен

+2

Что делать, если вы '.catch (ошибка => this._apiConnector.handleError (ошибка)) '? – Abdulrahman

ответ

21

Проблема заключается в том, что вы ссылаетесь на функцию непосредственно, так что вы потеряете свой контекст. Я имею в виду, что это теперь действие и метод.

Есть два способа исправить это:

  • обязательные функции для этого:

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

    Этот подход не рекомендуется, потому что вы потеряете типы здесь. Смотрите эту ссылку для получения более подробной информации: https://basarat.gitbooks.io/typescript/content/docs/tips/bind.html

  • оберточной вызов в функцию стрелки:

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

Этот ответ был правильным, с одной небольшой настройкой. Метод catch требует, чтобы вы что-то возвращали, поэтому в скобках требуется 'return'. – user43138

+2

Вы возвращаете что-то, если хотите выбросить новую или ту же ошибку: «return Observable.throw (error);». Если это не ваше дело, не возвращайтесь. Ошибка не будет распространяться на другой улов или на второй обратный вызов подписки. –

+2

У меня была такая же проблема, и этот ответ решил. Однако мне нравится решение без скобок и без возможности «_apiConnector» лучше. .catch (error => this.handleError (ошибка)); ' – hogan

Смежные вопросы