Dio网络请求框架之DioMixin源码分析(五)

DioMixin(Dio实现类)

abstract class DioMixin implements Dio {
  /// Default Request config. More see [BaseOptions].
  @override
  late BaseOptions options;

  /// Each Dio instance has a interceptor by which you can intercept requests or responses before they are
  /// handled by `then` or `catchError`. the [interceptor] field
  /// contains a [RequestInterceptor] and a [ResponseInterceptor] instance.
  final Interceptors _interceptors = Interceptors();

  @override
  Interceptors get interceptors => _interceptors;

  @override
  late HttpClientAdapter httpClientAdapter;

  @override
  Transformer transformer = BackgroundTransformer();


  bool _closed = false;
}

用作其他类继承或混合的基类。

下面是DioMixin类的主要属性和方法:

  • options:默认的请求配置,类型为BaseOptions,用于设置请求的默认参数,如请求超时时间、请求头等。
  • interceptors:拦截器,类型为Interceptors,用于拦截请求和响应,并进行相应的处理。通过拦截器,可以在请求或响应被处理之前进行自定义操作。
  • httpClientAdapter:HTTP客户端适配器,用于发送HTTP请求。具体的实现可以根据需要进行配置。
  • transformer:数据转换器,用于对请求和响应的数据进行转换。默认使用BackgroundTransformer,可以自定义实现其他的转换器。
  • _closed:表示Dio实例是否已关闭的标志。当调用close方法关闭Dio实例时,该标志会被设置为true

DioMixin类提供了一些默认的属性和方法实现,方便其他类进行扩展和定制。通过继承或混合DioMixin类,可以快速构建自定义的Dio实例,并使用其中的属性和方法来发送HTTP请求。

close

void close({bool force = false}) {
  _closed = true;
  httpClientAdapter.close(force: force);
}

close方法是DioMixin类中的一个方法,用于关闭Dio实例。

下面是close方法的作用:

  • _closed属性设置为true,表示Dio实例已关闭。
  • 调用httpClientAdapterclose方法来关闭底层的HTTP客户端适配器。

参数说明:

  • force(可选):是否强制关闭,默认为false。当设置为true时,会立即关闭所有活动的连接以释放所有资源;当设置为false时,会等待所有活动的连接完成后再关闭。

通过调用close方法,可以关闭Dio实例并释放相关资源,确保在不再需要使用Dio实例时进行清理操作。

get

Future<Response<T>> get<T>(String path, {
  Map<String, dynamic>? queryParameters,
  Object? data,
  Options? options,

  CancelToken? cancelToken,

  ProgressCallback? onReceiveProgress,
}) {




  return request<T>(
    path,
    data: data,
    queryParameters: queryParameters,
    options: checkOptions('GET', options),
    onReceiveProgress: onReceiveProgress,
    cancelToken: cancelToken,
  );




}




get方法是DioMixin类中的一个方法,用于发送HTTP GET请求。

下面是get方法的作用:

  • 使用request方法发送HTTP GET请求,传递相应的参数。
  • 参数path表示请求的URL路径。
  • 参数queryParameters(可选)表示请求的查询参数。
  • 参数data(可选)表示请求的数据。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onReceiveProgress(可选)表示接收进度的回调函数。

通过调用get方法,可以方便地发送HTTP GET请求,并返回对应的Future<Response>对象,用于处理响应结果。

getUri

Future<Response<T>> getUri<T>(Uri uri, {
  Object? data,







  Options? options,



  CancelToken? cancelToken,



  ProgressCallback? onReceiveProgress,
}) {


  return requestUri<T>(
    uri,
    data: data,
    options: checkOptions('GET', options),
    onReceiveProgress: onReceiveProgress,
    cancelToken: cancelToken,



  );



}



getUri方法是DioMixin类中的一个方法,用于发送HTTP GET请求。

下面是getUri方法的作用:

  • 使用requestUri方法发送HTTP GET请求,传递相应的参数。
  • 参数uri表示请求的完整URI。
  • 参数data(可选)表示请求的数据。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onReceiveProgress(可选)表示接收进度的回调函数。

通过调用getUri方法,可以方便地发送HTTP GET请求,并返回对应的Future<Response>对象,用于处理响应结果。

post

Future<Response<T>> post<T>(String path, {
  Object? data,







  Map<String, dynamic>? queryParameters,


  Options? options,



  CancelToken? cancelToken,


  ProgressCallback? onSendProgress,


  ProgressCallback? onReceiveProgress,


}) {


  return request<T>(


    path,


    data: data,


    options: checkOptions('POST', options),
    queryParameters: queryParameters,
    cancelToken: cancelToken,


    onSendProgress: onSendProgress,


    onReceiveProgress: onReceiveProgress,


  );



}


post方法是DioMixin类中的一个方法,用于发送HTTP POST请求。

下面是post方法的作用:

  • 使用request方法发送HTTP POST请求,传递相应的参数。
  • 参数path表示请求的路径。
  • 参数data(可选)表示请求的数据。
  • 参数queryParameters(可选)表示请求的查询参数。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onSendProgress(可选)表示发送进度的回调函数。
  • 参数onReceiveProgress(可选)表示接收进度的回调函数。

通过调用post方法,可以方便地发送HTTP POST请求,并返回对应的Future<Response>对象,用于处理响应结果。

postUri

Future<Response<T>> postUri<T>(Uri uri, {
  Object? data,







  Options? options,



  CancelToken? cancelToken,



  ProgressCallback? onSendProgress,



  ProgressCallback? onReceiveProgress,



}) {




  return requestUri<T>(


    uri,


    data: data,



    options: checkOptions('POST', options),
    cancelToken: cancelToken,



    onSendProgress: onSendProgress,



    onReceiveProgress: onReceiveProgress,



  );




}




postUri方法是DioMixin类中的一个方法,用于发送HTTP POST请求。

下面是postUri方法的作用:

  • 使用requestUri方法发送HTTP POST请求,传递相应的参数。
  • 参数uri表示请求的URI。
  • 参数data(可选)表示请求的数据。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onSendProgress(可选)表示发送进度的回调函数。
  • 参数onReceiveProgress(可选)表示接收进度的回调函数。

通过调用postUri方法,可以方便地发送HTTP POST请求,并返回对应的Future<Response>对象,用于处理响应结果。

put

Future<Response<T>> put<T>(String path, {
  Object? data,







  Map<String, dynamic>? queryParameters,


  Options? options,



  CancelToken? cancelToken,


  ProgressCallback? onSendProgress,


  ProgressCallback? onReceiveProgress,


}) {


  return request<T>(


    path,


    data: data,


    queryParameters: queryParameters,

    options: checkOptions('PUT', options),
    cancelToken: cancelToken,


    onSendProgress: onSendProgress,


    onReceiveProgress: onReceiveProgress,


  );



}


put方法是DioMixin类中的一个方法,用于发送HTTP PUT请求。

下面是put方法的作用:

  • 使用request方法发送HTTP PUT请求,传递相应的参数。
  • 参数path表示请求的路径。
  • 参数data(可选)表示请求的数据。
  • 参数queryParameters(可选)表示请求的查询参数。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onSendProgress(可选)表示发送进度的回调函数。
  • 参数onReceiveProgress(可选)表示接收进度的回调函数。

通过调用put方法,可以方便地发送HTTP PUT请求,并返回对应的Future<Response>对象,用于处理响应结果。

putUri

Future<Response<T>> putUri<T>(Uri uri, {
  Object? data,







  Options? options,



  CancelToken? cancelToken,



  ProgressCallback? onSendProgress,



  ProgressCallback? onReceiveProgress,



}) {




  return requestUri<T>(


    uri,


    data: data,



    options: checkOptions('PUT', options),
    cancelToken: cancelToken,



    onSendProgress: onSendProgress,



    onReceiveProgress: onReceiveProgress,



  );




}




putUri方法是DioMixin类中的一个方法,用于发送HTTP PUT请求。

下面是putUri方法的作用:

  • 使用requestUri方法发送HTTP PUT请求,传递相应的参数。
  • 参数uri表示请求的完整URI。
  • 参数data(可选)表示请求的数据。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onSendProgress(可选)表示发送进度的回调函数。
  • 参数onReceiveProgress(可选)表示接收进度的回调函数。

通过调用putUri方法,可以方便地发送HTTP PUT请求,并返回对应的Future<Response>对象,用于处理响应结果。

head

Future<Response<T>> head<T>(String path, {
  Object? data,


  Map<String, dynamic>? queryParameters,
  Options? options,

  CancelToken? cancelToken,

}) {


  return request<T>(

    path,

    data: data,
    queryParameters: queryParameters,
    options: checkOptions('HEAD', options),
    cancelToken: cancelToken,
  );



}



head方法是DioMixin类中的一个方法,用于发送HTTP HEAD请求。

下面是head方法的作用:

  • 使用request方法发送HTTP HEAD请求,传递相应的参数。
  • 参数path表示请求的路径。
  • 参数data(可选)表示请求的数据。
  • 参数queryParameters(可选)表示请求的查询参数。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。

通过调用head方法,可以方便地发送HTTP HEAD请求,并返回对应的Future<Response>对象,用于处理响应结果。

headUri

Future<Response<T>> headUri<T>(Uri uri, {
  Object? data,


  Options? options,

  CancelToken? cancelToken,


}) {

  return requestUri<T>(

    uri,

    data: data,

    options: checkOptions('HEAD', options),
    cancelToken: cancelToken,

  );

}

headUri方法是DioMixin类中的一个方法,用于发送HTTP HEAD请求,并通过URI参数指定请求的URL。

下面是headUri方法的作用:

  • 使用requestUri方法发送HTTP HEAD请求,传递相应的参数。
  • 参数uri表示请求的URI,用于指定请求的URL。
  • 参数data(可选)表示请求的数据。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。

通过调用headUri方法,可以方便地发送HTTP HEAD请求,并返回对应的Future<Response>对象,用于处理响应结果。

delete

Future<Response<T>> delete<T>(String path, {
  Object? data,
  Map<String, dynamic>? queryParameters,
  Options? options,
  CancelToken? cancelToken,
}) {


  return request<T>(

    path,

    data: data,
    queryParameters: queryParameters,
    options: checkOptions('DELETE', options),
    cancelToken: cancelToken,
  );



}



delete方法是DioMixin类中的一个方法,用于发送HTTP DELETE请求。

下面是delete方法的作用:

  • 使用request方法发送HTTP DELETE请求,传递相应的参数。
  • 参数path表示请求的路径,用于指定请求的URL。
  • 参数data(可选)表示请求的数据。
  • 参数queryParameters(可选)表示请求的查询参数。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。

通过调用delete方法,可以方便地发送HTTP DELETE请求,并返回对应的Future<Response>对象,用于处理响应结果。

deleteUri

Future<Response<T>> deleteUri<T>(Uri uri, {
  Object? data,


  Options? options,

  CancelToken? cancelToken,


}) {

  return requestUri<T>(

    uri,

    data: data,

    options: checkOptions('DELETE', options),
    cancelToken: cancelToken,

  );

}

deleteUri方法是DioMixin类中的一个方法,用于发送HTTP DELETE请求。

下面是deleteUri方法的作用:

  • 使用requestUri方法发送HTTP DELETE请求,传递相应的参数。
  • 参数uri表示请求的完整URI,用于指定请求的URL。
  • 参数data(可选)表示请求的数据。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。

通过调用deleteUri方法,可以方便地发送HTTP DELETE请求,并返回对应的Future<Response>对象,用于处理响应结果。

patch

Future<Response<T>> patch<T>(String path, {
  Object? data,







  Map<String, dynamic>? queryParameters,


  Options? options,



  CancelToken? cancelToken,


  ProgressCallback? onSendProgress,


  ProgressCallback? onReceiveProgress,


}) {


  return request<T>(


    path,


    data: data,


    queryParameters: queryParameters,

    options: checkOptions('PATCH', options),
    cancelToken: cancelToken,


    onSendProgress: onSendProgress,


    onReceiveProgress: onReceiveProgress,


  );



}


patch方法是DioMixin类中的一个方法,用于发送HTTP PATCH请求。

下面是patch方法的作用:

  • 使用request方法发送HTTP PATCH请求,传递相应的参数。
  • 参数path表示请求的路径,用于指定请求的URL路径。
  • 参数data(可选)表示请求的数据。
  • 参数queryParameters(可选)表示请求的查询参数。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onSendProgress(可选)表示请求发送进度的回调函数。
  • 参数onReceiveProgress(可选)表示请求接收进度的回调函数。

通过调用patch方法,可以方便地发送HTTP PATCH请求,并返回对应的Future<Response>对象,用于处理响应结果。

patchUri

Future<Response<T>> patchUri<T>(Uri uri, {
  Object? data,







  Options? options,



  CancelToken? cancelToken,



  ProgressCallback? onSendProgress,



  ProgressCallback? onReceiveProgress,



}) {




  return requestUri<T>(


    uri,


    data: data,



    options: checkOptions('PATCH', options),
    cancelToken: cancelToken,



    onSendProgress: onSendProgress,



    onReceiveProgress: onReceiveProgress,



  );




}




patchUri方法是DioMixin类中的一个方法,用于发送HTTP PATCH请求。

下面是patchUri方法的作用:

  • 使用requestUri方法发送HTTP PATCH请求,传递相应的参数。
  • 参数uri表示请求的完整URI,用于指定请求的URL。
  • 参数data(可选)表示请求的数据。
  • 参数options(可选)表示请求的配置选项。
  • 参数cancelToken(可选)表示用于取消请求的CancelToken实例。
  • 参数onSendProgress(可选)表示请求发送进度的回调函数。
  • 参数onReceiveProgress(可选)表示请求接收进度的回调函数。

通过调用patchUri方法,可以方便地发送HTTP PATCH请求,并返回对应的Future<Response>对象,用于处理响应结果。

downloadUri

Future<Response> downloadUri(Uri uri,
    dynamic savePath, {

      ProgressCallback? onReceiveProgress,

      CancelToken? cancelToken,
      bool deleteOnError = true,
      String lengthHeader = Headers.contentLengthHeader,
      Object? data,
      Options? options,
    }) {
  return download(
    uri.toString(),
    savePath,
    onReceiveProgress: onReceiveProgress,
    lengthHeader: lengthHeader,
    deleteOnError: deleteOnError,
    cancelToken: cancelToken,

    data: data,
    options: options,
  );
}

downloadUri方法是DioMixin类中的一个方法,用于从指定的URI下载文件。

下面是downloadUri方法的作用:

  • 使用download方法下载文件,传递相应的参数。
  • 参数uri表示下载文件的URI,用于指定文件的URL。
  • 参数savePath表示下载文件保存的路径。
  • 参数onReceiveProgress(可选)表示下载进度的回调函数。
  • 参数cancelToken(可选)表示用于取消下载的CancelToken实例。
  • 参数deleteOnError(可选)表示是否在下载发生错误时删除已下载的文件,默认为true
  • 参数lengthHeader(可选)表示用于获取文件长度的HTTP头字段,默认为Headers.contentLengthHeader
  • 参数data(可选)表示下载请求的数据。
  • 参数options(可选)表示下载请求的配置选项。

通过调用downloadUri方法,可以方便地从指定的URI下载文件,并返回对应的Future<Response>对象,用于处理下载结果。

download

Future<Response> download(String urlPath,
    dynamic savePath, {

      ProgressCallback? onReceiveProgress,

      Map<String, dynamic>? queryParameters,
      CancelToken? cancelToken,
      bool deleteOnError = true,
      String lengthHeader = Headers.contentLengthHeader,
      Object? data,
      Options? options,
    }) {
  throw UnsupportedError(
    'download() is not available in the current environment.',
  );



}



这个download方法是在DioMixin类中定义的,用于在特定环境中下载文件。

这个方法抛出了一个UnsupportedError异常,表示在当前环境中不支持下载操作。可能是因为当前环境没有提供相应的下载功能或者相关的依赖库未安装。

如果你想在当前环境中实现下载功能,你可以自行编写适合当前环境的下载方法,或者使用其他支持下载的库。

requestUri

Future<Response<T>> requestUri<T>(Uri uri, {
  Object? data,







  CancelToken? cancelToken,
  Options? options,



  ProgressCallback? onSendProgress,



  ProgressCallback? onReceiveProgress,



}) {




  return request(
    uri.toString(),
    data: data,



    cancelToken: cancelToken,
    options: options,
    onSendProgress: onSendProgress,



    onReceiveProgress: onReceiveProgress,



  );




}




requestUri 方法是一个用于发送 HTTP 请求的便捷方法,它会将传入的 Uri 对象转换为字符串,并调用 request 方法来发送请求。

requestUri 方法中,你可以指定要发送的请求的 Uri、请求数据、取消令牌、请求选项以及发送和接收进度回调。它会将这些参数转发给 request 方法来执行实际的请求。

如果你想要使用 requestUri 方法发送请求,你可以提供一个 Uri 对象,以及其他可选的参数。然后,requestUri 方法将使用 uri.toString()Uri 对象转换为字符串,并将其传递给 request 方法来发送请求。

请注意,requestUri 方法返回一个 Future<Response<T>> 对象,该对象表示发送请求后的响应。你可以使用 await 关键字等待响应的到达,或者使用 .then.catchError 方法处理响应。

request

Future<Response<T>> request<T>(String path, {
  Object? data,
  Map<String, dynamic>? queryParameters,
  CancelToken? cancelToken,


  Options? options,
  ProgressCallback? onSendProgress,
  ProgressCallback? onReceiveProgress,
}) async {
  final requestOptions = (options ?? Options()).compose(
    this.options,
    path,
    data: data,
    queryParameters: queryParameters,
    onReceiveProgress: onReceiveProgress,
    onSendProgress: onSendProgress,
    cancelToken: cancelToken,

    sourceStackTrace: StackTrace.current,
  );


  if (_closed) {
    throw DioError.connectionError(
      reason: "Dio can't establish a new connection after it was closed.",
      requestOptions: requestOptions,
    );
  }

  return fetch<T>(requestOptions);
}

request 方法是一个用于发送 HTTP 请求的便捷方法。它接受一个路径(path)参数,以及其他可选的参数,如请求数据(data)、查询参数(queryParameters)、取消令牌(cancelToken)、请求选项(options)以及发送和接收进度回调。

request 方法中,首先使用传入的参数构建了一个 RequestOptions 对象,用于描述请求的各种选项和配置。这里使用了 compose 方法,它会将传入的参数与 Dio 实例的默认选项进行合并,生成最终的请求选项。

然后,检查 _closed 属性来确定 Dio 实例是否已关闭。如果已关闭,则抛出一个 DioError 异常,指示无法在关闭后建立新的连接。

最后,调用 fetch<T> 方法,将构建的 requestOptions 作为参数,发送实际的请求,并返回一个 Future<Response<T>> 对象,表示发送请求后的响应。

如果你想要使用 request 方法发送请求,你可以提供一个路径(path)以及其他可选的参数。request 方法将使用这些参数构建请求选项,并发送请求。注意,你也可以通过修改默认选项 options 来自定义请求的行为。

请注意,request 方法是一个异步方法,返回一个 Future 对象,你可以使用 await 关键字等待响应的到达,或者使用 .then.catchError 方法处理响应。

fetch

抓取网络请求数据

requestInterceptorWrapper

Future<Response<T>> fetch<T>(RequestOptions requestOptions) async {
  if (T != dynamic &&
      !(requestOptions.responseType == ResponseType.bytes ||
          requestOptions.responseType == ResponseType.stream)) {
    if (T == String) {
      requestOptions.responseType = ResponseType.plain;
    } else {
      requestOptions.responseType = ResponseType.json;
    }
  }

  // Convert the request interceptor to a functional callback in which
  // we can handle the return value of interceptor callback.
  
以下代码中,`requestInterceptorWrapper`函数的返回类型是`FutureOr Function(dynamic)`,它定义了一个接受`dynamic`类型参数的函数,并返回`FutureOr`类型的结果。
  
  FutureOr Function(dynamic) requestInterceptorWrapper(InterceptorSendCallback interceptor,) {
    return (dynamic incomingState) async {
      final state = incomingState as InterceptorState;
      if (state.type == InterceptorResultType.next) {
        return listenCancelForAsyncTask(
          requestOptions.cancelToken,
          Future(() {
            final requestHandler = RequestInterceptorHandler();
            interceptor(state.data as RequestOptions, requestHandler);
            return requestHandler.future;
          }),
        );
      } else {
        return state;
      }
    };
  }
}

这段代码定义了一个函数 requestInterceptorWrapper,它将一个拦截器回调函数 interceptor 包装成另一个函数。这个包装后的函数接收一个动态类型的参数 incomingState,并返回一个 FutureOr 对象。

具体解释如下:

  • incomingState 被强制转换为 InterceptorState 类型,并赋值给变量 state

  • 如果 statetype 属性等于 InterceptorResultType.next,则执行下面的代码块。

    • 调用 listenCancelForAsyncTask 函数,传递 requestOptions.cancelToken 和一个 Future 对象。
    • Future 对象中创建一个 RequestInterceptorHandler 实例 requestHandler
    • 调用拦截器回调函数 interceptor,传递 state.data(强制转换为 RequestOptions 类型)和 requestHandler
    • 返回 requestHandler.future,即一个 Future 对象。
  • 如果 statetype 属性不等于 InterceptorResultType.next,则直接返回 state 对象。

这行代码的作用是将拦截器回调函数 interceptor 包装成一个能够处理异步任务的函数,并根据 state 的类型进行不同的处理。如果 state 的类型为 InterceptorResultType.next,则执行拦截器回调函数,并将返回的结果包装在一个 Future 中;否则,直接返回 state 对象。

_requestInterceptorWrapper

FutureOr _requestInterceptorWrapper() {
  return Future.value(2);
}

这段代码定义了一个函数 _requestInterceptorWrapper,它返回一个 FutureOr 对象。

具体解释如下:

  • _requestInterceptorWrapper 函数没有参数。
  • 在函数体内部,使用 Future.value(2) 创建一个已完成的 Future 对象,其值为 2。
  • 返回这个已完成的 Future 对象作为 FutureOr 对象。

这行代码的作用是创建一个已完成的 Future 对象,并将其作为 FutureOr 对象返回。这个已完成的 Future 对象的值是 2。

responseInterceptorWrapper

FutureOr<dynamic> Function(dynamic) responseInterceptorWrapper(InterceptorSuccessCallback interceptor,) {
  return (dynamic incomingState) async {
    final state = incomingState as InterceptorState;
    if (state.type == InterceptorResultType.next || state.type == InterceptorResultType.resolveCallFollowing) {
      return listenCancelForAsyncTask(
        requestOptions.cancelToken,
        Future(() {
          final responseHandler = ResponseInterceptorHandler();
          interceptor(state.data as Response, responseHandler);
          return responseHandler.future;
        }),
      );
    } else {

      return state;
    }

  };
}

这段代码定义了一个函数 responseInterceptorWrapper,它接受一个参数 interceptor,类型为 InterceptorSuccessCallback,并返回一个 FutureOr<dynamic> Function(dynamic) 对象。

具体解释如下:

  • responseInterceptorWrapper 函数接受一个回调函数 interceptor,该回调函数的类型为 InterceptorSuccessCallback

  • 在函数体内部,定义了一个异步函数,接受一个参数 incomingState,类型为 dynamic

  • 在异步函数体内部,首先将 incomingState 强制转换为 InterceptorState 类型,并将其赋值给变量 state

  • 接下来,通过检查 statetype 属性,判断执行不同的逻辑。

    • 如果 state.type 的值为 InterceptorResultType.nextInterceptorResultType.resolveCallFollowing,表示需要执行成功的拦截器回调函数。

      • 在这种情况下,调用 listenCancelForAsyncTask 方法,传递 requestOptions.cancelToken 和一个异步函数作为参数。
      • 在异步函数体内,首先创建一个 ResponseInterceptorHandler 对象,并将 state.data(类型为 Response)和该处理器对象传递给拦截器回调函数 interceptor
      • 返回 responseHandler.future,即一个 Future 对象,该对象在处理器对象中的 future 属性被解析时完成。
    • 如果 state.type 的值不是上述两种情况,则直接返回 state

这行代码的作用是创建一个函数 responseInterceptorWrapper,该函数接受一个拦截器回调函数作为参数,并根据传入的状态类型执行相应的逻辑。如果状态类型符合条件,则调用拦截器回调函数并返回相应的 Future 对象,否则直接返回状态对象。返回的函数可以用作请求流程中的响应拦截器

errorInterceptorWrapper

FutureOr<dynamic> Function(Object) errorInterceptorWrapper(InterceptorErrorCallback interceptor,) {
  return (err) {
    final state = err is InterceptorState ? err : InterceptorState(assureDioError(err, requestOptions));
    Future<InterceptorState> handleError() async {
      final errorHandler = ErrorInterceptorHandler();
      interceptor(state.data, errorHandler);
      return errorHandler.future;
    }

    // The request has already been canceled,
    // there is no need to listen for another cancellation.
    if (state.data is DioError && state.data.type == DioErrorType.cancel) {
      return handleError();
    } else if (state.type == InterceptorResultType.next ||
        state.type == InterceptorResultType.rejectCallFollowing) {
      return listenCancelForAsyncTask(
        requestOptions.cancelToken,
        Future(handleError),
      );
    } else {
      throw err;
    }
  };
}

这段代码定义了一个函数 errorInterceptorWrapper,它接受一个参数 interceptor,类型为 InterceptorErrorCallback,并返回一个 FutureOr<dynamic> Function(Object) 对象。

具体解释如下:

  • errorInterceptorWrapper 函数接受一个回调函数 interceptor,该回调函数的类型为 InterceptorErrorCallback

  • 在函数体内部,定义了一个匿名函数,接受一个参数 err,类型为 Object

  • 在匿名函数体内部,首先判断 err 是否为 InterceptorState 类型,如果是,则将 err 赋值给变量 state;如果不是,则通过 assureDioError 方法将 errrequestOptions 转换为 InterceptorState 类型,并将结果赋值给变量 state

  • 接下来,定义了一个异步函数 handleError,用于处理错误。

  • 在异步函数体内部,首先创建一个 ErrorInterceptorHandler 对象,并将 state.data 和该处理器对象传递给拦截器回调函数 interceptor

  • 根据不同的条件进行处理:

    • 如果 state.dataDioError 类型且其 type 属性为 DioErrorType.cancel,表示请求已被取消,不需要再监听其他取消操作。此时调用 handleError 函数处理错误。

    • 如果 state.type 的值为 InterceptorResultType.nextInterceptorResultType.rejectCallFollowing,表示需要执行拒绝的拦截器回调函数。

      • 在这种情况下,调用 listenCancelForAsyncTask 方法,传递 requestOptions.cancelToken 和一个异步函数 handleError 作为参数。
    • 如果上述条件都不满足,则抛出原始错误 err

  • 返回的函数可以用作请求流程中的错误处理器。

这段代码的作用是创建一个函数 errorInterceptorWrapper,该函数接受一个拦截器回调函数作为参数,并根据传入的错误状态类型执行相应的逻辑。根据错误状态的不同,可能会调用拦截器回调函数进行处理或抛出错误。返回的函数可以用作请求流程中的错误处理器。

future

// Build a request flow in which the processors(interceptors)
// execute in FIFO order.

// Start the request flow
Future<dynamic> future = Future<dynamic>(() => InterceptorState(requestOptions));

这段代码构建了一个请求流程,其中处理器(拦截器)按照先进先出(FIFO)的顺序执行。

具体解释如下:

  • 首先,使用 Future<dynamic> 构造了一个 future 对象,并将其初始化为一个立即执行的 Future
  • Future<dynamic>(() => InterceptorState(requestOptions)) 表达式中的箭头函数 () => InterceptorState(requestOptions) 用于创建一个初始的 InterceptorState 对象,并作为 Future 的返回值。
  • 这个初始的 InterceptorState 对象包含了请求的配置信息 requestOptions
  • 这个 future 对象标志着请求流程的开始。

接下来的代码会在这个初始的 future 对象的基础上继续构建请求流程,依次添加请求拦截器、请求派发、响应拦截器和错误处理器。每个处理器都会按照先进先出的顺序执行,并根据需要对请求或响应进行处理。最终,请求流程的结果将被返回。

Add request interceptors to request flow

// Add request interceptors to request flow
for (final interceptor in interceptors) {

  final fun = interceptor is QueuedInterceptor ? interceptor._handleRequest : interceptor.onRequest;
  future = future.then(requestInterceptorWrapper(fun));
}



// Add dispatching callback to request flow
future = future.then(
  requestInterceptorWrapper((RequestOptions reqOpt,
      RequestInterceptorHandler handler,) {
    requestOptions = reqOpt;
    _dispatchRequest<T>(reqOpt).then((value) => handler.resolve(value, true)).catchError((e) {
      handler.reject(e as DioError, true);
    });
  }),
);

这段代码向请求流程中添加了请求拦截器,并在最后添加了一个派发请求的回调函数。

具体解释如下:

  • 首先,通过 for 循环遍历 interceptors 列表,其中的每个元素都是一个请求拦截器。
  • 对于每个拦截器,使用条件判断 interceptor is QueuedInterceptor 来确定使用不同的处理函数。如果是 QueuedInterceptor 类型的拦截器,则使用 _handleRequest 函数,否则使用 onRequest 函数。将相应的处理函数赋值给变量 fun
  • 然后,通过 future.then(requestInterceptorWrapper(fun)) 将处理函数包装成一个回调函数,并将其添加到请求流程中。requestInterceptorWrapper 函数用于包装拦截器的处理函数,使其能够在异步任务中执行,并处理回调结果。
  • 循环结束后,请求流程中已经添加了所有的请求拦截器。

接下来,通过 future.then(...) 添加了一个派发请求的回调函数到请求流程中。该回调函数使用 requestInterceptorWrapper 包装,处理请求的派发操作。

  • 在回调函数中,首先将 reqOpt(请求配置)赋值给 requestOptions,用于后续请求的处理。
  • 然后,调用 _dispatchRequest<T>(reqOpt) 发起请求,并使用 then 方法处理请求的结果。如果请求成功,调用 handler.resolve(value, true) 将结果传递给请求处理器;如果请求失败,使用 catchError 捕获异常,并调用 handler.reject(e as DioError, true) 将异常传递给请求处理器。
  • 最后,将这个派发请求的回调函数包装成一个回调函数,并添加到请求流程中。

这样,请求流程中已经添加了所有的请求拦截器和派发请求的回调函数,它们会按照先进先出的顺序执行,并在请求流程中逐步处理请求和响应。

Add response interceptors to request flow

// Add response interceptors to request flow
for (final interceptor in interceptors) {

  final fun = interceptor is QueuedInterceptor ? interceptor._handleResponse : interceptor.onResponse;
  future = future.then(responseInterceptorWrapper(fun));
}



// Add error handlers to request flow
for (final interceptor in interceptors) {
  final fun = interceptor is QueuedInterceptor ? interceptor._handleError : interceptor.onError;
  future = future.catchError(errorInterceptorWrapper(fun));
}

// Normalize errors, we convert error to the DioError.
return future.then<Response<T>>((data) {
  return assureResponse<T>(
    data is InterceptorState ? data.data : data,
    requestOptions,
  );



}).catchError((Object e) {
  final isState = e is InterceptorState;
  if (isState) {
    if (e.type == InterceptorResultType.resolve) {
      return assureResponse<T>(e.data, requestOptions);
    }
  }
  throw assureDioError(isState ? e.data : e, requestOptions);
});

这段代码向请求流程中添加了响应拦截器和错误处理器,并对错误进行了规范化处理。

具体解释如下:

  • 首先,通过 for 循环遍历 interceptors 列表,其中的每个元素都是一个拦截器。
  • 对于每个拦截器,使用条件判断 interceptor is QueuedInterceptor 来确定使用不同的处理函数。如果是 QueuedInterceptor 类型的拦截器,则使用 _handleResponse 函数作为响应拦截器;否则使用 onResponse 函数作为响应拦截器。将相应的处理函数赋值给变量 fun
  • 然后,通过 future.then(responseInterceptorWrapper(fun)) 将处理函数包装成一个回调函数,并将其添加到请求流程中。responseInterceptorWrapper 函数用于包装拦截器的处理函数,使其能够在异步任务中执行,并处理回调结果。
  • 循环结束后,请求流程中已经添加了所有的响应拦截器。

接下来,通过另一个 for 循环遍历 interceptors 列表,向请求流程中添加了错误处理器。

  • 对于每个拦截器,使用条件判断 interceptor is QueuedInterceptor 来确定使用不同的处理函数。如果是 QueuedInterceptor 类型的拦截器,则使用 _handleError 函数作为错误处理器;否则使用 onError 函数作为错误处理器。将相应的处理函数赋值给变量 fun
  • 通过 future.catchError(errorInterceptorWrapper(fun)) 将错误处理函数包装成一个回调函数,并将其添加到请求流程中。errorInterceptorWrapper 函数用于包装错误处理器的处理函数,使其能够在异步任务中执行,并处理回调结果。

接下来,通过链式调用 thencatchError 方法,对请求流程中的结果进行处理。

  • 通过 future.then<Response<T>>((data) { ... }) 方法添加一个回调函数,用于处理请求流程中的结果。在这个回调函数中,根据结果的类型进行规范化处理。

  • 如果结果是 InterceptorState 类型,则将其数据部分提取出来,即 data.data,作为响应数据;如果结果不是 InterceptorState 类型,则直接将结果作为响应数据。

  • 调用 assureResponse<T>(...) 方法将响应数据和请求配置传递给 assureResponse 函数,以获取经过规范化处理的响应对象。

  • 最后,通过 catchError 方法添加一个回调函数,用于处理请求流程中的错误。在这个回调函数中,首先判断错误是否是 InterceptorState 类型。

  • 如果是 InterceptorState 类型,进一步判断其类型是否为 InterceptorResultType.resolve。如果是,则将其数据部分作为响应数据,调用 `assureResponse(…)

  • 在错误处理的回调函数中,如果错误对象的类型是 InterceptorState,则进一步判断其类型是否为 InterceptorResultType.resolve。如果是这种情况,表示错误已被处理并解决,可以将其数据部分作为响应数据。

  • 如果不是 InterceptorState 类型或者不是 InterceptorResultType.resolve 类型,则需要将错误进行规范化处理。调用 assureDioError 函数将错误对象和请求配置传递进去,以获得经过规范化处理的 DioError 对象。

  • 最后,使用 throw 关键字抛出规范化处理后的错误,以终止请求流程并向上层传递错误。

    整体来说,这段代码构建了一个请求流程,其中的处理器(拦截器)按照先进先出的顺序执行。首先,添加请求拦截器和请求分发回调函数到请求流程中,然后添加响应拦截器和错误处理器。最后,对请求流程中的结果进行规范化处理,确保返回的响应是经过正确处理的对象。如果出现错误,则将错误规范化处理并向上层抛出。

    请注意,这段代码是在异步环境中执行的,使用 Futurethen 方法来构建异步任务链。

listenCancelForAsyncTask

static Future<T> listenCancelForAsyncTask<T>(CancelToken? cancelToken,
    Future<T> future,) {
  return Future.any([
    if (cancelToken != null) cancelToken.whenCancel.then((e) => throw e),
    future,
  ]);
}

listenCancelForAsyncTask 是一个静态方法,其作用是监听取消令牌(CancelToken)和异步任务,并返回其中最先完成的结果。

  • cancelToken:取消令牌,用于取消异步任务。
  • future:要执行的异步任务。

方法内部使用了 Future.any 方法,它接受一个 Iterable,并返回其中最先完成的 Future 对象。在这个方法中,我们传入了两个 Future 对象:

  • 如果 cancelToken 不为空,我们通过 cancelToken.whenCancel 方法创建了一个 Future,当取消令牌触发取消事件时,该 Future 会抛出对应的取消异常。
  • future 是传入的要执行的异步任务。

因此,listenCancelForAsyncTask 方法返回的是最先完成的 Future 对象,无论是成功完成任务还是被取消。如果取消令牌触发了取消事件,将抛出取消异常,否则返回异步任务的结果。

这个方法的作用是在异步任务执行期间监听取消令牌,并及时处理取消事件,以提供对取消操作的支持。

_dispatchRequest

Future<Response<dynamic>> _dispatchRequest<T>(RequestOptions reqOpt) async {
  final cancelToken = reqOpt.cancelToken;
  ResponseBody responseBody;
  try {
    final stream = await _transformData(reqOpt);
    responseBody = await httpClientAdapter.fetch(
      reqOpt,
      stream,
      cancelToken?.whenCancel,
    );
    final headers = Headers.fromMap(responseBody.headers);
    // Make sure headers and responseBody.headers point to a same Map
    responseBody.headers = headers.map;
    final ret = Response<dynamic>(
      headers: headers,
      requestOptions: reqOpt,
      redirects: responseBody.redirects ?? [],
      isRedirect: responseBody.isRedirect,
      statusCode: responseBody.statusCode,
      statusMessage: responseBody.statusMessage,
      extra: responseBody.extra,
    );
    final statusOk = reqOpt.validateStatus(responseBody.statusCode);
    if (statusOk || reqOpt.receiveDataWhenStatusError == true) {
      ret.data = await transformer.transformResponse(reqOpt, responseBody);
    } else {
      await responseBody.stream.listen(null).cancel();
    }
    checkCancelled(cancelToken);
    if (statusOk) {
      return ret;
    } else {
      throw DioError.badResponse(
        statusCode: responseBody.statusCode,
        requestOptions: reqOpt,
        response: ret,
      );
    }
  } catch (e) {
    throw assureDioError(e, reqOpt);
  }
}

_dispatchRequest 是一个私有方法,用于实际发送请求并处理响应。它接受一个 RequestOptions 参数 reqOpt,表示请求的选项。

  • reqOpt:请求的选项,包括请求的URL、方法、头部、超时设置等信息。

方法内部的逻辑如下:

  1. 首先获取请求的取消令牌 cancelToken

  2. 尝试将请求数据进行转换,获取转换后的数据流 stream

  3. 使用 httpClientAdapter 发送请求并获取响应的 responseBody。同时传入取消令牌的 whenCancel 方法,以便在取消请求时得到通知。

  4. 创建响应的头部对象 headers,并确保 responseBody.headersheaders 引用相同的 Map 对象。

  5. 创建一个空的 Response<dynamic> 对象 ret,并将响应相关的信息赋值给该对象。

  6. 检查响应的状态码是否符合预期,如果符合或者请求选项中设置了在状态码错误时接收响应数据,则进行数据转换。

    • 如果状态码符合预期或者需要在状态码错误时接收响应数据,将调用转换器的 transformResponse 方法,将响应数据进行转换,并将转换后的结果赋值给 ret.data
    • 如果状态码不符合预期且不需要在状态码错误时接收响应数据,则取消响应的数据流。
  7. 检查请求是否被取消,如果取消则抛出 DioError 异常。

  8. 根据响应的状态码判断响应是否成功。如果成功,则返回 ret 对象作为响应结果。

  9. 如果响应状态码不符合预期,则抛出 DioError.badResponse 异常,其中包含响应的状态码、请求选项和响应对象作为错误信息。

  10. 如果出现异常,使用 assureDioError 方法将异常对象转换为 DioError 对象,并抛出。

因此,_dispatchRequest 方法的作用是实际发送请求并处理响应。它将请求的数据转换为请求适配器可接受的格式,并使用适配器发送请求并获取响应。然后,根据响应的状态码和请求选项进行处理,最后返回相应的 Response 对象或抛出适当的异常。

assureResponse

static Response<T> assureResponse<T>(Object response,
    RequestOptions requestOptions,) {

  if (response is! Response) {
    return Response<T>(
      data: response as T,
      requestOptions: requestOptions,
    );
  } else if (response is! Response<T>) {
    final T? data = response.data as T?;
    final Headers headers;
    if (data is ResponseBody) {
      headers = Headers.fromMap(data.headers);
    } else {

      headers = response.headers;
    }

    return Response<T>(
      data: data,
      headers: headers,
      requestOptions: response.requestOptions,
      statusCode: response.statusCode,
      isRedirect: response.isRedirect,
      redirects: response.redirects,
      statusMessage: response.statusMessage,
      extra: response.extra,
    );
  }
  return response;
}

assureResponse 是一个静态方法,用于确保返回的响应对象的类型符合预期。它接受两个参数:response(响应对象)和 requestOptions(请求选项)。

  • response:要进行类型确认的响应对象。
  • requestOptions:请求选项。

方法内部的逻辑如下:

  1. 首先检查 response 是否是 Response 类型的实例,如果不是,则将其作为数据(data)进行包装,创建一个新的 Response<T> 对象,并使用传入的 requestOptions 进行初始化。

  2. 如果 responseResponse 类型的实例,但不是 Response<T> 类型的实例,那么我们需要根据其数据类型进行进一步处理。

    • 如果 response.dataResponseBody 类型的实例,我们从中提取头部信息(headers)并创建一个新的 Headers 对象。
    • 否则,我们使用原始响应的头部信息。 最后,我们创建一个新的 Response<T> 对象,将数据、头部信息以及其他相关属性(状态码、是否重定向、重定向信息等)复制到新的对象中。
  3. 如果 response 的类型已经是 Response<T>,则直接返回该对象。

因此,assureResponse 方法的作用是确保返回的响应对象的类型符合预期,并进行必要的类型转换和包装。

assureDioError

static DioError assureDioError(Object err,
    RequestOptions requestOptions,) {

  if (err is DioError) {
    // nothing to be done
    return err;
  }
  return DioError(
    requestOptions: requestOptions,
    error: err,
  );
}

assureDioError 是一个静态方法,用于确保错误对象的类型符合 DioError 的预期。它接受两个参数:err(错误对象)和 requestOptions(请求选项)。

  • err:要进行类型确认的错误对象。
  • requestOptions:请求选项。

方法内部的逻辑如下:

  1. 首先检查 err 是否已经是 DioError 类型的实例,如果是,则直接返回该错误对象。
  2. 如果 err 不是 DioError 类型的实例,我们将其作为错误信息(error)进行包装,并使用传入的 requestOptions 进行初始化,创建一个新的 DioError 对象。
  3. 返回新创建的 DioError 对象。

因此,assureDioError 方法的作用是确保错误对象的类型符合 DioError 的预期,并进行必要的类型转换和包装。如果错误对象已经是 DioError 类型的实例,则直接返回该对象,否则创建一个新的 DioError 对象。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYC51bA7' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片