2016-03-25 13 views
14

Tự hỏi liệu bạn có thể hỗ trợ một chút hay không. Tôi có vẻ hơi bối rối khi nói đến việc sử dụng catch với Observable s. Về cơ bản những gì tôi đang cố gắng làm là như sau: Khi API của tôi trả về lỗi 403, tôi muốn thực hiện một số hành động trên TokenStore, cụ thể là xóa mã thông báo cục bộ và đánh dấu người dùng là chưa được xác thực. Cách tôi đang cố gắng để làm điều này có thể sai, vì vậy xin vui lòng cho tôi biết nếu có một cách tốt hơn để hoàn thành điều này.Angular2- Bắt nhầm lẫn với phạm vi đóng mở Catchable

Tôi đang cố gắng để thực hiện điều này với đoạn mã sau:

APIConnector.service.ts - một dịch vụ duy nhất cho các phương pháp giao tiếp 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') }); 
    } 
} 

Trong mỗi dịch vụ của tôi mà sử dụng APIConnector, tôi có phương pháp bắt trên Observable s, để chạy đóng cửa handleError. ví dụ.

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); 
} 

Tuy nhiên, điều này mang lại các lỗi sau:

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

Có lẽ điều này là do HandleError là một đóng cửa. Tôi không chắc chắn cách tốt nhất để đối phó với điều này, mặc dù.

Bất kỳ ý tưởng nào sẽ được đánh giá rất cao

+2

gì nếu bạn làm '.catch (lỗi => this._apiConnector.handleError (lỗi)) '? – Abdulrahman

Trả lời

21

Vấn đề là bạn tham chiếu hàm trực tiếp để bạn mất ngữ cảnh. Tôi có nghĩa là nó bây giờ là sự tiếp cận và một phương pháp.

Có hai cách để sửa lỗi này:

  • ràng buộc chức năng này:

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

    Cách tiếp cận này là không nên vì bạn sẽ mất các loại đây. Xem liên kết này để biết thêm chi tiết: https://basarat.gitbooks.io/typescript/content/docs/tips/bind.html

  • gói các cuộc gọi vào một chức năng mũi tên:

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

Câu trả lời này là chính xác, với một điều chỉnh nhỏ. Phương thức catch yêu cầu bạn trả về một cái gì đó, do đó, một 'return' được yêu cầu trong các dấu ngoặc vuông. – user43138

+2

Bạn trả lại một cái gì đó nếu bạn muốn ném một lỗi mới hoặc tương tự: "return Observable.throw (error);". Nếu không phải trường hợp của bạn, đừng quay lại. Lỗi sẽ không được tuyên truyền cho một lần đánh bắt khác hoặc đến lần gọi lại thứ hai của đăng ký. –

+2

Tôi gặp vấn đề tương tự và câu trả lời này đã giải quyết được vấn đề. Tuy nhiên tôi thích giải pháp mà không có dấu ngoặc và không có '_apiConnector' cách tốt hơn '.catch (error => this.handleError (error));' – hogan