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
实例已关闭。 - 调用
httpClientAdapter
的close
方法来关闭底层的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
。 -
如果
state
的type
属性等于InterceptorResultType.next
,则执行下面的代码块。- 调用
listenCancelForAsyncTask
函数,传递requestOptions.cancelToken
和一个Future
对象。 - 在
Future
对象中创建一个RequestInterceptorHandler
实例requestHandler
。 - 调用拦截器回调函数
interceptor
,传递state.data
(强制转换为RequestOptions
类型)和requestHandler
。 - 返回
requestHandler.future
,即一个Future
对象。
- 调用
-
如果
state
的type
属性不等于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
。 -
接下来,通过检查
state
的type
属性,判断执行不同的逻辑。-
如果
state.type
的值为InterceptorResultType.next
或InterceptorResultType.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
方法将err
和requestOptions
转换为InterceptorState
类型,并将结果赋值给变量state
。 -
接下来,定义了一个异步函数
handleError
,用于处理错误。 -
在异步函数体内部,首先创建一个
ErrorInterceptorHandler
对象,并将state.data
和该处理器对象传递给拦截器回调函数interceptor
。 -
根据不同的条件进行处理:
-
如果
state.data
是DioError
类型且其type
属性为DioErrorType.cancel
,表示请求已被取消,不需要再监听其他取消操作。此时调用handleError
函数处理错误。 -
如果
state.type
的值为InterceptorResultType.next
或InterceptorResultType.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
函数用于包装错误处理器的处理函数,使其能够在异步任务中执行,并处理回调结果。
接下来,通过链式调用 then
和 catchError
方法,对请求流程中的结果进行处理。
-
通过
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
关键字抛出规范化处理后的错误,以终止请求流程并向上层传递错误。整体来说,这段代码构建了一个请求流程,其中的处理器(拦截器)按照先进先出的顺序执行。首先,添加请求拦截器和请求分发回调函数到请求流程中,然后添加响应拦截器和错误处理器。最后,对请求流程中的结果进行规范化处理,确保返回的响应是经过正确处理的对象。如果出现错误,则将错误规范化处理并向上层抛出。
请注意,这段代码是在异步环境中执行的,使用
Future
和then
方法来构建异步任务链。
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、方法、头部、超时设置等信息。
方法内部的逻辑如下:
-
首先获取请求的取消令牌
cancelToken
。 -
尝试将请求数据进行转换,获取转换后的数据流
stream
。 -
使用
httpClientAdapter
发送请求并获取响应的responseBody
。同时传入取消令牌的whenCancel
方法,以便在取消请求时得到通知。 -
创建响应的头部对象
headers
,并确保responseBody.headers
和headers
引用相同的 Map 对象。 -
创建一个空的
Response<dynamic>
对象ret
,并将响应相关的信息赋值给该对象。 -
检查响应的状态码是否符合预期,如果符合或者请求选项中设置了在状态码错误时接收响应数据,则进行数据转换。
- 如果状态码符合预期或者需要在状态码错误时接收响应数据,将调用转换器的
transformResponse
方法,将响应数据进行转换,并将转换后的结果赋值给ret.data
。 - 如果状态码不符合预期且不需要在状态码错误时接收响应数据,则取消响应的数据流。
- 如果状态码符合预期或者需要在状态码错误时接收响应数据,将调用转换器的
-
检查请求是否被取消,如果取消则抛出
DioError
异常。 -
根据响应的状态码判断响应是否成功。如果成功,则返回
ret
对象作为响应结果。 -
如果响应状态码不符合预期,则抛出
DioError.badResponse
异常,其中包含响应的状态码、请求选项和响应对象作为错误信息。 -
如果出现异常,使用
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
:请求选项。
方法内部的逻辑如下:
-
首先检查
response
是否是Response
类型的实例,如果不是,则将其作为数据(data
)进行包装,创建一个新的Response<T>
对象,并使用传入的requestOptions
进行初始化。 -
如果
response
是Response
类型的实例,但不是Response<T>
类型的实例,那么我们需要根据其数据类型进行进一步处理。- 如果
response.data
是ResponseBody
类型的实例,我们从中提取头部信息(headers
)并创建一个新的Headers
对象。 - 否则,我们使用原始响应的头部信息。 最后,我们创建一个新的
Response<T>
对象,将数据、头部信息以及其他相关属性(状态码、是否重定向、重定向信息等)复制到新的对象中。
- 如果
-
如果
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
:请求选项。
方法内部的逻辑如下:
- 首先检查
err
是否已经是DioError
类型的实例,如果是,则直接返回该错误对象。 - 如果
err
不是DioError
类型的实例,我们将其作为错误信息(error
)进行包装,并使用传入的requestOptions
进行初始化,创建一个新的DioError
对象。 - 返回新创建的
DioError
对象。
因此,assureDioError
方法的作用是确保错误对象的类型符合 DioError
的预期,并进行必要的类型转换和包装。如果错误对象已经是 DioError
类型的实例,则直接返回该对象,否则创建一个新的 DioError
对象。