You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 21:15:01