用RxJs让axios支持重试

2,922 阅读1分钟

axios是前端常用的http请求库,在业务中希望增加重试功能,本来通过自己简单的封装也能实现这个功能,详见我以前的帖子,本着杀鸡用牛刀的精神通过RxJs为axios增加这个功能

未改造前的函数

import axios from 'axios'

const get = (url, data) => {
  return axios.get(url, { params: data })
}

改造后

import axios from 'axios'
import { defer } from 'rxjs'
import { retry } from 'rxjs/operators';

const get = (url, data) => {
  return new Promise((resolve,reject)=>{
    defer(() => axios.get(url, { params: data }))
    .pipe(retry(3))
    .subscribe({next: resolve,error: reject})
  })
}

调用测试

get('./data.json',{a:1}).then(res=>{
  console.log('then',res)
}).catch(res=>{
  console.log('catch',res)
})

测试结果 异常测试(data2.json不存在)

get('./data2.json',{a:1}).then(res=>{
  console.log('then',res)
}).catch(res=>{
  console.log('catch',res)
})

测试结果

上面是出现错误后简单的重试,往往在实际项目中我们不希望出错后立刻重试,如果能延时一小段时间再重试就好了,下面再改进一下支持延时重试

import axios from 'axios'
import { defer } from 'rxjs'
import { retryWhen,delay,take } from 'rxjs/operators'

const get = (url, data) => {
  return new Promise((resolve,reject)=>{
    defer(() => axios.get(url, { params: data }))
    .pipe(retryWhen(errors => errors.pipe(delay(3000),take(3))))
    .subscribe({next: resolve,error: reject})
  })
}

测试结果,通过时间瀑布可以看到延时效果

上面的延迟重试实现了,但是有个问题,异常信息不会输出出来,也就是get的catch方法不会执行,因此还需要再此改进

import axios from 'axios'
import { defer } from 'rxjs'
import { retryWhen,delay,scan } from 'rxjs/operators'

const get = (url, data) => {
  return new Promise((resolve,reject)=>{
    defer(() => axios.get(url, { params: data }))
    .pipe(retryWhen(errors =>errors.pipe(scan((count,err)=>{
        if(count>3)throw new Error(err)
        return count+1
      },0),delay(3000))
    ))
    .subscribe({next: resolve,error: reject})
  })
}

再次测试,发现异常信息又可以正常输出了