Reputation: 2597
I'm trying to create a class for working with API on top of Angular2 HTTP
class. The main thing is that I need to add custom auth header which is available after user authorized.
The main problem is that the token is stored in Ionic Storage module from which it can be only be obtained asynchronously, but I need to return the specific type....
export class APIRequest extends Http {
private storage : Storage;
constructor (backend: XHRBackend, options: RequestOptions) {
super(backend, options);
this.storage = new Storage;
}
request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
if (typeof url === 'string') {
url = AppConfig.API_SERVER + url
} else {
url.url = AppConfig.API_SERVER + url.url
}
this.storage.get('authToken').then(token => {
if (typeof url === 'string') {
if (!options) {
options = {headers: new Headers()};
}
options.headers.set('Authorization', `Bearer ${token}`);
} else {
url.headers.set('Authorization', `Bearer ${token}`);
}
// Here I need to return
}, err => {
// throw some error
})
return super.request(url, options).catch(this.catchAuthError(this));
}
}
So basically I need somehow to put return super.request(url, options)...
to the promise of the storage and return when i get that token.
Upvotes: 5
Views: 4423
Reputation: 7719
Close to being a duplicate. (Couln't find it)
At least, the answer can be applied to the same problem. If you want to keep the returning Observable
a fix would be to convert your Promise
(this.storage.get
) to an Observable
.
After, you can use a operator like flapMap
to return the value of super.request
.
(Note: Compiler doesn't understand that it's returning a Response
now, so change return type to Observable<any>
(will still return Response
))
export class APIRequest extends Http {
private storage : Storage;
constructor (backend: XHRBackend, options: RequestOptions) {
super(backend, options);
this.storage = new Storage;
}
// any return type (will return Response object but compiler doesn't understand that)
request(url: string|Request, options?: RequestOptionsArgs): Observable<any> {
if (typeof url === 'string') {
url = AppConfig.API_SERVER + url
} else {
url.url = AppConfig.API_SERVER + url.url
}
//convert the Promise to an Observable
val storageObservable = Observable.fromPromise(this.sotrage.get('authToken'));
// rxjs/add/operator/mergeMap
return storageObservable.flatMap(token => {
if (typeof url === 'string') {
if (!options) {
options = {headers: new Headers()};
}
options.headers.set('Authorization', `Bearer ${token}`);
} else {
url.headers.set('Authorization', `Bearer ${token}`);
}
// the value that will be returned
return super.request(url, options).catch(this.catchAuthError(this));
}, err => {
// throw some error
})
}
}
Useful links:
Upvotes: 5