如何在 Dart 中取消延迟的未来?
How to make a delayed future cancelable in Dart?
假设在 Dart/Flutter 中您有以下代码:
void myOperation() {
// could be anything
print('you didn't cancel me!');
}
请注意,操作本身不是异步的并且是无效的 -- return 什么都没有。
我们希望它在将来的某个时候执行,但我们也希望能够取消它(因为已请求一个新的操作来取代它)。
我是这样开始的:
Future.delayed(Duration(seconds: 2), myOperation())
...但这是不可取消的。
您如何准确安排该“操作”,同时又使其可取消?
我在想...我们可以像这样修改代码:
Future.delayed(Duration(seconds: 2), () {
if (youStillWantThisToExecute) {
print('you didn't cancel me!');
}
});
但这并不是很好,因为它依赖于一个“全局”布尔值...所以如果布尔值被翻转为 false,则不会完成任何操作,即使是最近请求的操作,也就是我们想要的操作完成。
如果有一种方法可以创建任意数量的操作实例并逐一取消它们,或者为每个操作分配一个唯一的 id,而不是使用一个布尔值控制是否执行...以具有“mostRecentId”int 或在执行之前检查的内容。
总之...
CancelableOperation 的名字似乎很有前途。
所以,我查看了它的文档:
CancelableOperation.fromFuture(Future inner, {FutureOr onCancel()})
Creates a CancelableOperation wrapping inner. [...] factory
但老实说,这让我可怜的脑袋很痛。
我已经查阅了其他文章、问题和答案,但它们都是某些特定(和复杂)上下文的一部分,并且在任何地方都找不到一个简单的例子。
有没有办法通过将延迟的未来包装在其他 class 中来取消它?
能否请更有经验的人提供至少一个简单、完整、经过验证的在 DartPad 中编译的示例?
谢谢。
使用CancalableOperation
不会阻止print('hello');
执行,即使您取消也是如此。它所做的是取消(丢弃)结果(在您的情况下为无效)。我将使用 CancalableOperation
和 CancalableFuture
.
给你 2 个例子
CancelableOperation
例子
final delayedFuture = Future.delayed(
Duration(seconds: 2),
() {
return 'hello';
},
);
final cancellableOperation = CancelableOperation.fromFuture(
delayedFuture,
onCancel: () => {print('onCancel')},
);
cancellableOperation.value.then((value) => {
// Handle the future completion here
print('then: $value'),
});
cancellableOperation.value.whenComplete(() => {
print('onDone'),
});
cancellableOperation.cancel(); // <- commment this if you want to complete
CancelableFuture
例子
final delayedFuture = ...;
final cancalableFuture = CancelableFuture<String>(
future: delayedFuture,
onComplete: (result) {
// Use the result from the future to do stuff
print(result);
},
);
cancalableFuture.cancel(); // <- commment this if you want to complete
以及 CancelableFuture
实现
class CancelableFuture<T> {
bool _cancelled = false;
CancelableFuture({
@required Future<dynamic> future,
@required void Function(T) onComplete,
}) {
future.then((value) {
if (!_cancelled) onComplete(value);
});
}
void cancel() {
_cancelled = true;
}
}
您无法取消现有 Future
。如果你这样做:
Future.delayed(
Duration(seconds: 2),
() {
print('hello');
},
);
只要进程运行(并正在处理其事件队列)至少 2 秒,Future
最终将执行并打印 'hello'
。
充其量您可以导致 Future
的完成回调之一过早触发,以便调用者可以将操作视为已取消或失败,这就是 CancelableOperation
等。做。
编辑:
根据您更新的问题,现在具体询问 delayed Future
s,您应该考虑使用 Timer
,是可取消。 (但是,与 Future
不同,呼叫者不能直接等待 Timer
。如果这对您很重要,您需要创建一个 Completer
,让呼叫者在 Completer
的Future
,让Timer
的回调完成。)
使用定时器:
var t = Timer(Duration(seconds: 400), () async {
client.close(force: true);
});
...
t.cancel();
假设在 Dart/Flutter 中您有以下代码:
void myOperation() {
// could be anything
print('you didn't cancel me!');
}
请注意,操作本身不是异步的并且是无效的 -- return 什么都没有。
我们希望它在将来的某个时候执行,但我们也希望能够取消它(因为已请求一个新的操作来取代它)。
我是这样开始的:
Future.delayed(Duration(seconds: 2), myOperation())
...但这是不可取消的。
您如何准确安排该“操作”,同时又使其可取消?
我在想...我们可以像这样修改代码:
Future.delayed(Duration(seconds: 2), () {
if (youStillWantThisToExecute) {
print('you didn't cancel me!');
}
});
但这并不是很好,因为它依赖于一个“全局”布尔值...所以如果布尔值被翻转为 false,则不会完成任何操作,即使是最近请求的操作,也就是我们想要的操作完成。
如果有一种方法可以创建任意数量的操作实例并逐一取消它们,或者为每个操作分配一个唯一的 id,而不是使用一个布尔值控制是否执行...以具有“mostRecentId”int 或在执行之前检查的内容。
总之...
CancelableOperation 的名字似乎很有前途。
所以,我查看了它的文档:
CancelableOperation.fromFuture(Future inner, {FutureOr onCancel()}) Creates a CancelableOperation wrapping inner. [...] factory
但老实说,这让我可怜的脑袋很痛。
我已经查阅了其他文章、问题和答案,但它们都是某些特定(和复杂)上下文的一部分,并且在任何地方都找不到一个简单的例子。
有没有办法通过将延迟的未来包装在其他 class 中来取消它?
能否请更有经验的人提供至少一个简单、完整、经过验证的在 DartPad 中编译的示例?
谢谢。
使用CancalableOperation
不会阻止print('hello');
执行,即使您取消也是如此。它所做的是取消(丢弃)结果(在您的情况下为无效)。我将使用 CancalableOperation
和 CancalableFuture
.
CancelableOperation
例子
final delayedFuture = Future.delayed(
Duration(seconds: 2),
() {
return 'hello';
},
);
final cancellableOperation = CancelableOperation.fromFuture(
delayedFuture,
onCancel: () => {print('onCancel')},
);
cancellableOperation.value.then((value) => {
// Handle the future completion here
print('then: $value'),
});
cancellableOperation.value.whenComplete(() => {
print('onDone'),
});
cancellableOperation.cancel(); // <- commment this if you want to complete
CancelableFuture
例子
final delayedFuture = ...;
final cancalableFuture = CancelableFuture<String>(
future: delayedFuture,
onComplete: (result) {
// Use the result from the future to do stuff
print(result);
},
);
cancalableFuture.cancel(); // <- commment this if you want to complete
以及 CancelableFuture
实现
class CancelableFuture<T> {
bool _cancelled = false;
CancelableFuture({
@required Future<dynamic> future,
@required void Function(T) onComplete,
}) {
future.then((value) {
if (!_cancelled) onComplete(value);
});
}
void cancel() {
_cancelled = true;
}
}
您无法取消现有 Future
。如果你这样做:
Future.delayed(
Duration(seconds: 2),
() {
print('hello');
},
);
只要进程运行(并正在处理其事件队列)至少 2 秒,Future
最终将执行并打印 'hello'
。
充其量您可以导致 Future
的完成回调之一过早触发,以便调用者可以将操作视为已取消或失败,这就是 CancelableOperation
等。做。
编辑:
根据您更新的问题,现在具体询问 delayed Future
s,您应该考虑使用 Timer
,是可取消。 (但是,与 Future
不同,呼叫者不能直接等待 Timer
。如果这对您很重要,您需要创建一个 Completer
,让呼叫者在 Completer
的Future
,让Timer
的回调完成。)
使用定时器:
var t = Timer(Duration(seconds: 400), () async {
client.close(force: true);
});
...
t.cancel();