RetryPolicy
是Alamofire
中对RequestInterceptor
的又一满分实现。从名字就可以看出,它主要是满足请求出错后的各种重试策略。下面就一起来领略一番。
六大配置实现五种特性
retryLimit
:控制最大重试次数。超过该次数后就不在重试。默认值2
。exponentialBackoffBase
&exponentialBackoffScale
:这两个参数和当前重试次数一起控制两次重试直接的时间间隔。具体计算方法为:pow(exponentialBackoffBase, retryCount) * exponentialBackoffScale
。他们的默认值是2
和0.5
。你可以设置exponentialBackoffScale
为1
实现指数增长的时间间隔。retryableHTTPMethods
:控制哪些HTTP
方法可以重试。默认值[delete, get, head, options, put, trace]
。这些方法都是幂等的
。retryableHTTPStatusCodes
:控制哪些HTTP
响应状态码可以重试。默认值[408(请求超时), 500, 502, 503, 504]
。-
retryableURLErrorCodes
:控制哪些系统错误状态码
可以重试。默认值:backgroundSessionInUseByAnotherProcess
:后台Session
被占用backgroundSessionWasDisconnected
:请求处理过程中后台Session
被挂起或退出badServerResponse
:后台返回的错误的数据callIsActive
:请求过程中被来电打断cannotConnectToHost
:无法链接到主机cannotFindHost
:无法找到主机cannotLoadFromNetwork
:需要从网络下载数据,但又被加载策略限制在从缓存加载
dataNotAllowed
:WIFI 和蜂窝网络都没有链接dnsLookupFailed
:无法解析 DNSdownloadDecodingFailedMidStream
:下载过程中无法解码数据downloadDecodingFailedToComplete
:下载完成后无法解码数据internationalRoamingOff
:需要通过漫游时,该功能未打开networkConnectionLost
:请求过程中突然断网notConnectedToInternet
:无法建立网络连接。首次安装应用,没有获取网络权限时会是该错误码。secureConnectionFailed
:无法建立安全的网络连接serverCertificateHasBadDate
:SSL 证书无效或过期serverCertificateNotYetValid
:SSL 证书未生效timedOut
:超时
若上面的配置能满足需求,我们只需将该类配置在Session
上:
1 |
|
或发起请求时配置在Request
上:
1 |
|
这样,在遇到以上条件的失败请求就会自动进行重试。
这么丰富的配置其实现并不复杂
看到提供如此丰富的配置,你是不是认为其实现会异常复杂。其实不然。总体也就几行代码:
1 |
|
这个核心逻辑就这么几行代码。就是依次判断当前请求是否满足各个状态。紧接着是该方法的调用:
1 |
|
加上这个适配方法,我们可以配置的参数都用上了。这些就是整个RetryPolicy
的全貌。so easy 嘛 😂~~
有两点需要注意
为什么retryLimit
这个配置要单独拎出来判断
在适配方法中,我们发现这里是先判断了retryLimit
这个限制,然后再调用了核心的判断方法。为什么retryLimit
的判断没有在核心方法中判断?
我的想法是:retryLimit
这个条件是最容易触发false
的,在这种情况下,可以节省一次函数调用。希望有不同见解同学评论区告诉我,一起进步 😁。
retryableURLErrorCodes
没有覆盖到的点
虽然retryableURLErrorCodes
这个配置支持了notConnectedToInternet
这个错误码。但在应用首次安装,网络未授权时表现不佳。
考虑这个场景:用户第一次打开应用,弹出网络授权,然后在此状态停留。此时我们的应用并没有网络授权,然后请求会出错,根据这个重试策略,它会再次发出请求,然后还是错误….这样一直循环,知道重试次数用完。
解决方案
- 开启
URLSessionConfiguration
的waitsForConnectivity
配置。这个配置开启后会在没有网络连接时将请求挂起,等到有链接的时候再发出。但是只能在iOS 11.0
之后使用。(话说还有多少同学在跟11
之前的版本斗争?留个言我同情你下 😂) - 自己实现
RequestInterceptor
。在内部监听网络状态,根据状态决定是否重试。这个方案交给各位同学啦。
总结
今天学习了RetryPolicy
的使用及其实现。还发现了两个有趣的小问题。下节课再见。拜拜 👋🏻。