Android 使用cordova时,http请求的错误不起作用

Android 使用cordova时,http请求的错误不起作用,android,angular,cordova,ionic-framework,Android,Angular,Cordova,Ionic Framework,昨天我开发了一些离线功能。因此,我添加了一个ApiService,它返回可观察的对象。 目前,我获取用于jwt身份验证的access_令牌,然后使用该令牌为我的API请求生成头。请求成功后,我将结果保存到存储器中。这个很好用。现在我想检查一个不成功的请求(例如,服务器关闭,应用程序脱机),然后从存储中返回我存储的结果。但我不能让它工作 这是我的密码: getJobs(): Observable<any> { this.auth.checkToken() retur

昨天我开发了一些离线功能。因此,我添加了一个ApiService,它返回可观察的对象。 目前,我获取用于jwt身份验证的access_令牌,然后使用该令牌为我的API请求生成头。请求成功后,我将结果保存到存储器中。这个很好用。现在我想检查一个不成功的请求(例如,服务器关闭,应用程序脱机),然后从存储中返回我存储的结果。但我不能让它工作

这是我的密码:

  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))
      })
    )
  }
getJobs():可观察{
this.auth.checkToken()
从(this.storage.get(ACCESS_TOKEN))管道返回(
开关映射(令牌=>{
let options=this.auth.addToken(令牌)
返回此.http.get(API_URL+“作业”,选项)
}),
地图(res=>{
如果(res){
this.storage.set(作业、资源)
返回res
}否则{
从(this.storage.get(JOBS))返回
}
}),
捕获错误(()=>{
从(this.storage.get(JOBS))返回
})
)
}
进一步的调查表明,服务器或应用程序脱机后,map()和catchError()函数均未执行

更新: DJ House提供的解决方案是正确的。我的代码在我的浏览器中运行得很好,但是如果我用ionic cordova build android构建我的应用程序,它会在this.http.get(…)之后被卡住,所以它很清楚,并且与cordova有关

解决方案: 哇!神奇的事情发生了!我发现catchError方法会被调用,但在大约2分钟后,这是一种减慢速度的方法。。。因此,我将实现一个超时

谢谢
flixOflaks

请尝试将catchError操作符作为管道方法中的第一个操作符移动。这是为了确保您在接收到来自可观察对象的错误后立即捕获它。请按如下方式更改:

  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)
      }),
      catchError(() => {
        return from(this.storage.get(JOBS))
      })
      map(res => {
          if (res) {
            this.storage.set(JOBS, res)
            return res
          } else {
            return from(this.storage.get(JOBS))
          }
      }),
    )
  }
getJobs():可观察{
this.auth.checkToken()
从(this.storage.get(ACCESS_TOKEN))管道返回(
开关映射(令牌=>{
let options=this.auth.addToken(令牌)
返回此.http.get(API_URL+“作业”,选项)
}),
捕获错误(()=>{
从(this.storage.get(JOBS))返回
})
地图(res=>{
如果(res){
this.storage.set(作业、资源)
返回res
}否则{
从(this.storage.get(JOBS))返回
}
}),
)
}

请尝试将catchError操作符作为管道方法中的第一个操作符移动。这是为了确保您在接收到来自可观察对象的错误后立即捕获它。请按如下方式更改:

  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)
      }),
      catchError(() => {
        return from(this.storage.get(JOBS))
      })
      map(res => {
          if (res) {
            this.storage.set(JOBS, res)
            return res
          } else {
            return from(this.storage.get(JOBS))
          }
      }),
    )
  }
getJobs():可观察{
this.auth.checkToken()
从(this.storage.get(ACCESS_TOKEN))管道返回(
开关映射(令牌=>{
let options=this.auth.addToken(令牌)
返回此.http.get(API_URL+“作业”,选项)
}),
捕获错误(()=>{
从(this.storage.get(JOBS))返回
})
地图(res=>{
如果(res){
this.storage.set(作业、资源)
返回res
}否则{
从(this.storage.get(JOBS))返回
}
}),
)
}

您可能面临的主要问题是您不正确地使用了
地图。映射作用于一个正常值(通常,它不是一个可观察值)并返回一个新值
map()
应始终返回相同类型的值。在
map()
中,您要么返回响应(我假设它属于
Jobs
类型),要么返回一个
可观察的
。这将导致订阅服务器需要详细的逻辑来处理该问题

看起来您正试图使用该
map()
设置本地存储和api返回的作业。我建议使用,因为您不想更改返回的值

函数getJobs():可观察{
this.auth.checkToken()
从(this.storage.get(ACCESS_TOKEN))管道返回(
开关映射(令牌=>{
let options=this.auth.addToken(令牌)
返回此.http.get(API_URL+“作业”,选项)
}),
//更改为tap()
轻触(res=>{
如果(res){
this.storage.set(作业、资源)
}
}),
捕获错误(()=>{
从(this.storage.get(JOBS))返回
})
)
}

如果
开关映射
抛出错误,将跳过轻触。这将确保仅在从API接收值时设置存储。如果总是希望设置存储(即使API抛出错误),则将
tap()
移动到
catchError()
之后

您可能面临的主要问题是您不正确地使用了
map
。映射作用于一个正常值(通常,它不是一个可观察值)并返回一个新值
map()
应始终返回相同类型的值。在
map()
中,您要么返回响应(我假设它属于
Jobs
类型),要么返回一个
可观察的
。这将导致订阅服务器需要详细的逻辑来处理该问题

看起来您正试图使用该
map()
设置本地存储和api返回的作业。我建议使用,因为您不想更改返回的值

函数getJobs():可观察{
this.auth.checkToken()
从(this.storage.get(ACCESS_TOKEN))管道返回(
开关映射(令牌=>{
let options=this.auth.addToken(令牌)
返回此.http.get(API_URL+“作业”,选项)
}),
//更改为tap()
轻触(res=>{
如果(res){
this.storage.set(作业、资源)
}
}),
捕获错误(()=>{
从(this.storage.get(JOBS))返回
})
)
}
如果
开关映射
抛出错误,将跳过轻触。这将确保您仅在以下情况下设置存储: