I am using @angular/http for http calls (Observable) and NativeStorage library for storage mechanism which is Promise. That's why I use FromPromise to convert Promise funtion "NativeStorage.getItem("xxx")" to Observable.
I am even not sure if this is a good practice and the chain is broken at the line "console.log("HIT SUCCESSFULLY");" and stops executing the code.
Since there is no item called "externalAccessToken" in the storage, it is normal to catch the exception null in Promise but I don't understand why it stops executing after that.
Till now, I have tried to return something else other than null and using "Promise.reject()" which caused "Unhandled Promise rejection" error.
How can I keep the the code executing and hit the catch function of Observable
public getExternalAccessTokenFromStorage(): Observable<any> {
let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise.then(x => x)
.catch(() => {
console.log("HIT SUCCESSFULLY");
return null
}));
return getExternalAccessTokenFromStorage.map(x => {
console.log("NOT HIT AT ALL");
return x;
}).catch(() => {
console.log("NOT HIT AT ALL");
return null;
});
}
public getUserInfo(): Observable<StoredUserModel> {
//Get External Access Token From LocalStorage
return this.getExternalAccessTokenFromStorage().flatMap((x: IExternalAccessTokenBindingModel) => {
return this.getAccessTokenFromStorage().flatMap((accessToken: AccessTokenModel) => {
console.log("NOT HIT AT ALL");
let headers = new Headers();
headers.append("Authorization", "Bearer " + accessToken.access_token);
headers.append("Content-Type", "application/json");
let options = new RequestOptions({ headers: headers });
var externalBindingModel = JSON.stringify(x);
return this.http.post(this.baseUrl + '/api/Account/ExternalUserInfo', externalBindingModel, options).map((res: Response) => {
//ADD USER INTO NATIVESTORAGE
this.addUserIntoStorage(res.json());
return res.json();
});
});
}).catch(x => {
return this.getAccessTokenFromStorage().flatMap((accessToken: AccessTokenModel) => {
console.log("NOT HIT AT ALL");
let headers = new Headers();
headers.append("Authorization", "Bearer " + accessToken.access_token);
let options = new RequestOptions({ headers: headers });
return this.http.get(this.baseUrl + '/api/Account/UserInfo', options).map((res: Response) => {
//ADD USER INTO NATIVESTORAGE
let user: StoredUserModel = res.json();
this.addUserIntoStorage(res.json());
return user;
});
}).catch(error => {
return null;
});
});
}
UPDATED QUESTION:
I have removed Promise.catch and keep Observable.catch in order to catch unhandled exception in Observable;
public getExternalAccessTokenFromStorage(): Observable<any> {
let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise);
return getExternalAccessTokenFromStorage.map(x => {
return x;
}).catch(() => {
return null;
});
}
And I get the following error;
I am using @angular/http for http calls (Observable) and NativeStorage library for storage mechanism which is Promise. That's why I use FromPromise to convert Promise funtion "NativeStorage.getItem("xxx")" to Observable.
I am even not sure if this is a good practice and the chain is broken at the line "console.log("HIT SUCCESSFULLY");" and stops executing the code.
Since there is no item called "externalAccessToken" in the storage, it is normal to catch the exception null in Promise but I don't understand why it stops executing after that.
Till now, I have tried to return something else other than null and using "Promise.reject()" which caused "Unhandled Promise rejection" error.
How can I keep the the code executing and hit the catch function of Observable
public getExternalAccessTokenFromStorage(): Observable<any> {
let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise.then(x => x)
.catch(() => {
console.log("HIT SUCCESSFULLY");
return null
}));
return getExternalAccessTokenFromStorage.map(x => {
console.log("NOT HIT AT ALL");
return x;
}).catch(() => {
console.log("NOT HIT AT ALL");
return null;
});
}
public getUserInfo(): Observable<StoredUserModel> {
//Get External Access Token From LocalStorage
return this.getExternalAccessTokenFromStorage().flatMap((x: IExternalAccessTokenBindingModel) => {
return this.getAccessTokenFromStorage().flatMap((accessToken: AccessTokenModel) => {
console.log("NOT HIT AT ALL");
let headers = new Headers();
headers.append("Authorization", "Bearer " + accessToken.access_token);
headers.append("Content-Type", "application/json");
let options = new RequestOptions({ headers: headers });
var externalBindingModel = JSON.stringify(x);
return this.http.post(this.baseUrl + '/api/Account/ExternalUserInfo', externalBindingModel, options).map((res: Response) => {
//ADD USER INTO NATIVESTORAGE
this.addUserIntoStorage(res.json());
return res.json();
});
});
}).catch(x => {
return this.getAccessTokenFromStorage().flatMap((accessToken: AccessTokenModel) => {
console.log("NOT HIT AT ALL");
let headers = new Headers();
headers.append("Authorization", "Bearer " + accessToken.access_token);
let options = new RequestOptions({ headers: headers });
return this.http.get(this.baseUrl + '/api/Account/UserInfo', options).map((res: Response) => {
//ADD USER INTO NATIVESTORAGE
let user: StoredUserModel = res.json();
this.addUserIntoStorage(res.json());
return user;
});
}).catch(error => {
return null;
});
});
}
UPDATED QUESTION:
I have removed Promise.catch and keep Observable.catch in order to catch unhandled exception in Observable;
public getExternalAccessTokenFromStorage(): Observable<any> {
let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise);
return getExternalAccessTokenFromStorage.map(x => {
return x;
}).catch(() => {
return null;
});
}
And I get the following error;
Share Improve this question edited Jul 29, 2017 at 17:55 P.S. 16.4k14 gold badges65 silver badges86 bronze badges asked Jul 1, 2017 at 16:19 mctunamctuna 8714 gold badges19 silver badges42 bronze badges 7-
Why not use
Observable.catch
instead ofPromise.catch
, i.e. move the error handling out of thefromPromise
? – jonrsharpe Commented Jul 1, 2017 at 16:21 - I have tried that and it throws something like "unhandled error": item null exception. If you want I can produce and write the exact error – mctuna Commented Jul 1, 2017 at 16:23
- Yes, please give a minimal reproducible example without any extraneous detail. – jonrsharpe Commented Jul 1, 2017 at 16:24
- @jonrsharpe I have updated the questions – mctuna Commented Jul 1, 2017 at 16:34
-
2
Note that you need to return an observable from
catch
callback - learnrxjs.io/operators/error_handling/catch.html – jonrsharpe Commented Jul 1, 2017 at 16:40
2 Answers
Reset to default 3Catch
works exactly the same as the try / catch
clasues in programming.
Give the following example:
try {
throw new Error('bang');
} catch(ex) {
// do nothing
}
console.log('I'm still reachable');
We can reproduce the above with observable like this:
let o = Observable.create((observer)=>{
observer.error(new Error('bang'));
}).catch(()=>{
// do nothing
});
o.subscribe(()=>{
console.log('I'm still reachable');
});
If you want to catch and process an error, but then prevent code below from executing using try / catch
you would do this:
try {
throw new Error('bang');
} catch(ex) {
// do some logic here
throw ex;
}
console.log('I cannot be reached');
It's the same in observables. You have to re-throw the error or yield an observable that also fails.
let o = Observable.create((observer)=>{
observer.error(new Error('bang'));
}).catch((ex)=>{
// do some logic here
return Observable.throw(ex);
});
o.subscribe(()=>{
console.log('I cannot be reached');
});
The problem is that you're catching, but not handling the error. You will want to throw the error as an Observable.
public getExternalAccessTokenFromStorage(): Observable<any> {
let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise);
return getExternalAccessTokenFromStorage.map(x => {
return x;
}).catch((error: any) =>
Observable.throw(error.json().error || 'Server error');
);
}
You can then handle your response and error in the form of a promise:
this.getExternalAccessTokenFromStorage().subscribe(
res => console.log(res),
error => console.log(error));