使用Dio发起新API请求前如何取消当前正在运行的API请求
解决方案
借助Dio内置的CancelToken即可实现新请求发起时自动取消上一个未完成的请求,修改后的封装代码如下:
import 'package:dio/dio.dart'; class DioClient { static BaseOptions options = BaseOptions(baseUrl: baseUrl); final Dio _dio = Dio(options); // 存储当前请求的取消令牌 CancelToken? _currentCancelToken; Future<dynamic> postFormData({ dynamic data, required String url, dynamic header, }) async { // 发起新请求前先取消上一个未完成的请求 if (_currentCancelToken != null && !_currentCancelToken!.isCancelled) { _currentCancelToken!.cancel("新请求发起,已取消上一个请求"); } // 为当前请求生成新的取消令牌 _currentCancelToken = CancelToken(); final formData = FormData.fromMap(data); try { var response = await _dio.post( url, options: Options(headers: header), data: formData, // 绑定取消令牌到当前请求 cancelToken: _currentCancelToken, ); // 请求完成后清空令牌 _currentCancelToken = null; return response.data; } catch (e) { // 过滤请求取消的异常,避免影响正常业务错误逻辑 if (e is CancelError) { return null; } rethrow; } } }
核心修改说明
- 新增
_currentCancelToken私有变量存储当前正在执行请求的取消令牌 - 每次发起新请求前,先判断上一个请求的令牌是否处于活跃状态,活跃则直接调用取消方法
- 新请求生成新的
CancelToken实例,绑定到当前请求参数中 - 异常捕获中增加
CancelError类型判断,可按需处理取消请求的特殊逻辑,避免和普通请求错误混淆
扩展方案(按接口区分取消逻辑)
如果只需要相同URL的请求才取消上一个,不需要全局取消所有旧请求,可以用Map存储不同接口的取消令牌:
import 'package:dio/dio.dart'; class DioClient { static BaseOptions options = BaseOptions(baseUrl: baseUrl); final Dio _dio = Dio(options); // 按URL存储对应请求的取消令牌 final Map<String, CancelToken> _cancelTokenMap = {}; Future<dynamic> postFormData({ dynamic data, required String url, dynamic header, }) async { // 仅取消同URL的上一个未完成请求 if (_cancelTokenMap.containsKey(url) && !_cancelTokenMap[url]!.isCancelled) { _cancelTokenMap[url]!.cancel("同接口新请求发起,已取消上一个请求"); } // 为当前接口生成新的取消令牌 _cancelTokenMap[url] = CancelToken(); final formData = FormData.fromMap(data); try { var response = await _dio.post( url, options: Options(headers: header), data: formData, cancelToken: _cancelTokenMap[url], ); // 请求完成后移除对应接口的令牌 _cancelTokenMap.remove(url); return response.data; } catch (e) { if (e is CancelError) { _cancelTokenMap.remove(url); return null; } _cancelTokenMap.remove(url); rethrow; } } }
内容的提问来源于stack exchange,提问作者Avnish Nishad
相关产品推荐
相关产品推荐

