如何在Angular 8中联网恢复时重发失败的API请求?
处理网络中断导致的API请求失败重发方案
这是个非常常见的离线场景问题,我来给你梳理一套可落地的解决方案,核心思路就是先把失败请求存下来,等网络恢复后再自动重试,具体步骤如下:
1. 捕获并持久化失败请求
当API调用抛出网络相关异常(比如连接超时、Socket中断这类IOException)时,一定要把请求的关键信息持久化存储——别用内存存,重启APP就没了!建议用本地数据库(比如SQLite、Room)或者加密文件,存储的信息至少要包含:
- 请求URL、HTTP方法(GET/POST/PUT等)
- 请求体、请求头
- 重试次数、创建时间
- 唯一请求ID(用于幂等性校验)
举个Kotlin的示例代码:
// 定义失败请求的数据模型 data class FailedRequest( val id: String, val url: String, val method: String, val body: String?, val headers: Map<String, String>, val retryCount: Int, val createdAt: Long ) // 捕获网络异常时保存请求 try { apiService.submitFormData(formData) } catch (e: IOException) { // 判断是否是网络类异常(比如连接中断、无网络) if (isNetworkRelatedException(e)) { failedRequestDao.insert(FailedRequest( id = UUID.randomUUID().toString(), url = "https://your-api.com/submit", method = "POST", body = Gson().toJson(formData), headers = mapOf("Content-Type" to "application/json"), retryCount = 0, createdAt = System.currentTimeMillis() )) } }
2. 监听网络状态变化
需要监听系统的网络状态,当网络从断开恢复到连接时,触发重试逻辑。不同平台有不同的实现方式:
- Android:用
ConnectivityManager.NetworkCallback监听网络切换 - iOS:用
NWPathMonitor监控网络路径变化 - Web:监听
online/offline事件
3. 重发失败请求并更新状态
网络恢复后,取出所有未处理的失败请求,逐个重试:
- 重试成功:从存储中删除该请求,同时同步本地业务数据(比如标记提交状态为成功)
- 重试失败:更新重试次数,超过最大重试阈值(比如3次)后,标记为“永久失败”,可以提示用户手动重试
示例重试逻辑:
fun retryAllFailedRequests() { val unresolvedRequests = failedRequestDao.getAllUnresolved() coroutineScope.launch(Dispatchers.IO) { unresolvedRequests.forEach { request -> try { val response = apiClient.sendRequest( url = request.url, method = request.method, body = request.body, headers = request.headers ) if (response.isSuccessful) { // 重试成功,删除记录 failedRequestDao.delete(request) // 更新本地业务状态 updateLocalSubmissionStatus(request.id, isSuccess = true) } else { // 非网络错误(比如400/500),根据业务决定是否继续重试 if (request.retryCount < 3) { failedRequestDao.update(request.copy(retryCount = request.retryCount + 1)) } else { // 超过重试次数,标记为失败 failedRequestDao.markAsPermanentFailure(request.id) } } } catch (e: IOException) { // 还是网络问题,更新重试次数 if (request.retryCount < 3) { failedRequestDao.update(request.copy(retryCount = request.retryCount + 1)) } else { failedRequestDao.markAsPermanentFailure(request.id) } } } } }
4. 关键注意事项
- 幂等性必须保证:这是重中之重!重发请求可能导致重复提交,一定要给每个请求加唯一的
Request-ID,后端根据这个ID判断是否已经处理过;或者用PUT代替POST(符合REST规范的场景),让后端执行更新而非创建操作。 - 指数退避重试:别每次重试都立刻发,用指数退避策略(比如第一次等10s,第二次20s,第三次40s),避免给服务器造成压力。
- 用户感知:可以在APP内加个轻量通知,告诉用户“有提交请求正在重试”;如果永久失败,弹窗提示用户手动重新提交。
- 线程安全:所有持久化和重试操作都要在后台线程执行,别阻塞UI线程。
内容的提问来源于stack exchange,提问作者Rahul Dapke
相关产品推荐
相关产品推荐

