I need to handle 401 error correctly on my Ionic 3 app. The below mentioned error comes when the app has not been used for a few days and after that user tries to access the app. This app has a backend web API(django) and it uses jwt token to validate the user.
So can you tell me the correct workflow of handling this kind of use case on Ionic 3 app? I was unable to find out good resources to refer this on the web. If you have something to share, it would be great.
I have seen this URL where it mentioned about subscribe subjects. But I don't know how to implement such thing with the Ionic app. Any clue, please?
authProvider.ts
import { Injectable, } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Headers, RequestOptions, BaseRequestOptions } from '@angular/http';
import { Storage } from '@ionic/storage';
createHeader(headers: Headers) {
return new Promise((resolve, reject) => {
this.storage.get('loggedInUser')
.then((token: any) => {
if (token) headers.append('Authorization', 'token ' + token.token);
resolve(headers);
}, err => {
resolve(headers);
});
});
}
get(api) {
return new Observable(observer => {
let header = new Headers();
this.createHeader(header)
.then(() => {
let options = new BaseRequestOptions();
options.withCredentials = true;
options.headers = header;
this.http.get(api, options)
.subscribe(response => {
observer.next(response);
observer.complete();
}, (e) => {
observer.error(e);
});
})
})
}
Console error message:

retryWhen to the rescue !If you want to retry the call once you fixed things (like renewing a token or so) retryWhen() is the way to go.
public retryWhen(notifier: function(errors: Observable): Observable): ObservableReturns an Observable that mirrors the source Observable with the exception of an error. If the source Observable calls error, this method will emit the Throwable that caused the error to the Observable returned from notifier.
If that Observable calls complete or error then this method will call complete or error on the child subscription. Otherwise this method will resubscribe to the source Observable.
tldr :This operator will handle the errors and if the observable returned by the notifier function emits a value, will resubscribe to the previous Observable. But, if the Observable emitted by notifier throws an error, the error will be propagated.
get(api) {
let header = new Headers();
return Observable.fromPromise(this.createHeader(header))
.map(()=>{
let options = new BaseRequestOptions();
options.withCredentials = true;
options.headers = header;
return options
})
.switchMap((options)=>this.http.get(api, options))
.retryWhen((errors)=>errors.switchMap((err:Error| Response)=>{
if(err instanceof Response && err.status===401){
// handle 401
return this.someHandlingReturningAnObservable();
}
return Observable.throw(err);
}));
}
Here, this.someHandlingReturningAnObservable() returns an Observable. In this method you fix your problem (ask for a new token, etc) and when it emits its value, the observable chain will be replayed. non-401 errors are just not handled.
catch() me if you canIf you just want to handle the error and do nothing more (display an error page for example) you can use the catch() operator :
public catch(selector: function): ObservableCatches errors on the observable to be handled by returning a new observable or throwing an error.
get(api) {
let header = new Headers();
return Observable.fromPromise(this.createHeader(header))
.map(()=>{
let options = new BaseRequestOptions();
options.withCredentials = true;
options.headers = header;
return options
})
.switchMap((options)=>this.http.get(api, options))
.catch((err:Error| Response)=>{
if(err instanceof Response && err.status===401){
// handle 401
return this.someHandlingReturningAnObservable();
}
return Observable.throw(err);
});
}
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