Angular2-与Observable Catch闭包范围混淆

时间:2016-03-25 21:04:08

标签: angular scope closures

想知道你是否可以提供一些帮助。在将catchObservable s一起使用时,我似乎对自己有点困惑。

基本上我要做的是以下内容: 当我的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') });
    }
}

在我使用API​​Connector的每个服务中,我都在Observable上捕获方法,以运行handleError闭包。 e.g。

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:无法读取未定义的属性'destroy'

大概这是因为handleError是一个闭包。不过,我不确定解决这个问题的最佳方法。

任何想法都将不胜感激

1 个答案:

答案 0 :(得分:23)

问题是您直接引用该函数,因此会丢失其上下文。我的意思是它现在是一个功能和方法。

有两种方法可以解决这个问题:

  • 将函数绑定到此:

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

    不推荐使用此方法,因为此处会丢失类型。有关详细信息,请参阅此链接:https://basarat.gitbooks.io/typescript/content/docs/tips/bind.html

  • 将调用包装成箭头函数:

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