取消Future的方法,通过百度搜索得到答案,将future转为stream,stream中有取消的方法,可以取消listen中的回调。
这样如果要使用await关键字就不行了,使用stream后只能使用listen执行后续的方法,不够“优雅”。
有没有其他的办法呢,刚开始我并没有找到,现在知道了,于是水一篇文章。
无意中查看dio post方法的参数,看到有一个cancelToken,这个cancelToken是什么呢,又是怎么被使用的呢,于是点击去看看,
CancelToken里有一个Completer,返回一个future,调用cancel方法后调用_completer.complete参数是DioError,表示取消的原因。
void cancel([dynamic reason]) {
_cancelError = DioError(
type: DioErrorType.cancel,
error: reason,
requestOptions: requestOptions ?? RequestOptions(path: ''),
);
_cancelError!.stackTrace = StackTrace.current;
_completer.complete(_cancelError);
}
这个取消方法是在什么时候被设置的呢,查看调用post之后执行的代码,post最终执行调用dio_mixin里面的fetch方法。
这个方法里可以看到调用了listenCancelForAsyncTask这个函数,传入了cancelToken。
static Future listenCancelForAsyncTask(
CancelToken? cancelToken, Future future) {
return Future.any([
if (cancelToken != null) cancelToken.whenCancel.then((e) => throw e),
future,
]);
}
看到这里已经很明显了,使用了 Future.any,也就是再创建一个 Future通过Future.any就可以取消另外一个 Future (准确的说是在被取消的Future没有完成之前取消这个Future)。
于是我又用谷歌搜了一下,发现有一个CancelableOperation,但是我放到代码里之后并没有这个类,可能是版本的关系吧。
Future.any是肯定可以用的,个人感觉比转成stream要好。