Issue
So yesterday I was developing some sort of offline functionality. Therefore, I added an ApiService that returns Observables. Currently, I fetch my access_token for jwt-Authentication and then use this token to generate Headers for my API-Request. After a successful request, I save the result to my storage. This works fine. Now here is the problem I want to check for an unsuccessful request (e.g. servers are down, app is offline) and then return my stored result from storage. But I can't get it to work.
Here is my code:
getJobs(): Observable<any> {
this.auth.checkToken()
return from(this.storage.get(ACCESS_TOKEN)).pipe(
switchMap(token => {
let options = this.auth.addToken(token)
return this.http.get(API_URL + "jobs", options)
}),
map(res => {
if (res) {
this.storage.set(JOBS, res)
return res
} else {
return from(this.storage.get(JOBS))
}
}),
catchError(() => {
return from(this.storage.get(JOBS))
})
)
}
Further investigations have shown that after the server or the app is offline neither the map() nor the catchError() functions were executed.
UPDATE:
The solution provided by DJ House is correct. My Code works perfectly in my browser but if I build my app with ionic cordova build android
it gets stuck after the this.http.get(...)
So it's clearly and issue with cordova
SOLUTION: Wow! Something magical happened! I've found out that the catchError method gets called BUT after almost 2 Minutes, which is way to slow... So I will implement a timeout.
Thanks flixoflax
Solution
The main issue that you may be facing is you are using the map
incorrectly. Map acts upon a normal value (usually, its not an observable) and returns a new value. map()
should always return the same type of value. In your map()
you are either return the response (which I am assuming is of type Jobs
) OR you are return an Observable<Jobs>
. This will cause your subscribers to need verbose logic to handle that.
It looks like you are trying to use that map()
to set your local storage with the returned jobs from your api. I would recommend using tap()
since you aren't trying to change the value you are returning.
function getJobs(): Observable<any> {
this.auth.checkToken()
return from(this.storage.get(ACCESS_TOKEN)).pipe(
switchMap(token => {
let options = this.auth.addToken(token)
return this.http.get(API_URL + "jobs", options)
}),
// change to tap()
tap(res => {
if (res) {
this.storage.set(JOBS, res)
}
}),
catchError(() => {
return from(this.storage.get(JOBS))
})
)
}
If the switchMap
throws an error, the tap will be skipped. That will ensure you only set storage if you recieve a value from the API. If you always want to set the storage (even if the API threw an error) then move the tap()
to be after the catchError()
.
Answered By - DJ House
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.