Wondering if you can give a little assistance. I appear to be getting myself a bit confused when it comes to using catch
with Observable
s.
Basically what I'm trying to do is the following:
When my API returns a 403 error, I want to perform some actions on my TokenStore
, namely, delete the local token and mark the user as unauthenticated. The way I'm trying to do this may be wrong, so please do let me know if there's a better way of accomplishing this.
I'm trying to accomplish this with the following code:
APIConnector.service.ts - a single service for API communication methods
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') });
}
}
In each of my services which use the APIConnector, I have catch methods on the Observable
s, to run the handleError
closure. 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);
}
However, this gives the following error:
EXCEPTION: TypeError: Cannot read property 'destroy' of undefined
Presumably this is because handleError is a closure. I'm unsure of the best way to deal with this, though.
Any thoughts would be greatly appreciated
Observables are "lazy", meaning if no one is listening, nothing happens.
In your component's template file, you can subscribe to this observable using the async pipe. The async pipe handles the subscribe/unsubscribe events for you, so you no longer need onInit and onDestroy in your component's TS file. And that's it!
The RxJS isEmpty() operator returns an observable with a Boolean value indicating whether the observable was empty or not. It returns an output as true if the source observable is empty; otherwise, false.
Observables provide support for passing messages between parts of your application. They are used frequently in Angular and are a technique for event handling, asynchronous programming, and handling multiple values.
The problem is that you reference the function directly so you lose its context. I mean it's now afunction and a method.
There are two ways to fix this:
binding the function to this:
.catch(this._apiConnector.handleError.bind(this));
This approach isn't recommended because you will lose types here. See this link for more details: https://basarat.gitbooks.io/typescript/content/docs/tips/bind.html
wrapping the call into an arrow function:
.catch((error) => {
this._apiConnector.handleError(error);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With