RxJs: http请求超时处理

向后台发起API请求,但后台API不稳定,有时候超一分钟才能返回结果,有报5XX服务端的错误,那我们怎么处理这种情况呢。

直接看如下代码,使用retry + timeoutWith + catchError 组合

import {of, forkJoin, Observable, throwError} from 'rxjs';
import {catchError, map, mergeMap, retry, timeoutWith} from 'rxjs/operators';

return this.common.get(`https://xxx.com/api/xxx`)
      .pipe(
        retry(3),
        timeoutWith(15000, throwError(new Error('Http Timeout exceeds'))),
        map((res: any) => {
          return res.data;
        }),
        catchError(err => {
          console.log('Call API failed::', err);
          return of(initData);
        })
      );

如果向后台发起一次API请求,然后重试3次都失败,一共4次请求都失败,这4次请求所花费的时间如果小于15秒,那它是不会抛出超时的错误,而是抛出API的错误,否则的话,会抛出超时错误 。 也就是说timeoutWith里面设置的时间是与前面4次请求所花时间的总和来比较的。

拿我现在的项目来说, API 通常在第6秒抛出500错误,API的错误内容是: internal error.

下面代码的请求过程是这样的:

1. 发起第一次请求,等待了6秒,API 抛错  internal error.

2. retry第一次, 请求也花了6秒, 共花了12秒,API 继续抛错  internal error.

3. retry第二次,在请求等待第3秒时,(6+6+3 = 15),就不再继续等待了,API 还没来得及返回任何信息

4. 由于有timeoutWith(15秒),程序直接抛出了'Http Timeout exceeds'错误

5. catchError捕获了超时的错误,而不是API的internal error

注意:在步骤3这里,http 请求是未结束的,如果你在拦截器里写了http请求结束后的逻辑,它是不会被执行的。

这里在pipe里使用了三个函数:

  • retry: 重试3次
  • timeoutWith: 如果在5秒中内, API 没有返回结果,抛出'Http Timeout exceeds'错误, 其实也可以使用timeout 效果一样,只不过timeoutWith后面可以返回一个超时后的结果。比如timeoutWith(1500, of('hello'))
  • catchError: 无论是哪种错误,都会被catchError捕获

下面来一段更清晰的。推荐用这个编辑器(https://stackblitz.com/

// RxJS v6+
import { of,throwError, Observable } from 'rxjs';
import { retry, concatMap, mergeMap, timeout, timeoutWith, catchError, delay } from 'rxjs/operators';

// simulate request
function makeRequest(timeToDelay) {
 
  return of('Request Complete!').pipe(
    delay(timeToDelay),
    mergeMap(()=>{
      console.log('ttt');
      return throwError('1 timeout!')
    })
  );
}



makeRequest(4000).pipe(
  retry(3),
  timeoutWith(15000, throwError('Http Timeout exceeds')),
  catchError(error => {
    console.log(error);
    return of(`Request timed out after: 4000`)
  })
).subscribe(val => console.log(val));

结果为:

第一次请求,花了4秒, 打印ttt

第二次请求(retry 第一次),花了4秒,打印ttt

第三次请求(retry 第二次),花了4秒,打印ttt

第四次请求(retry 第三次),花了3秒 (4+4+4+3 = 15), 不等makeRequest返回就强制让它超时,并抛出'Http Timeout exceeds'超时错误

参考链接

https://www.learnrxjs.io/learn-rxjs/operators/utility/timeoutwith

发布了105 篇原创文章 · 获赞 46 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/wucong60/article/details/104534298
今日推荐