在Dart UI中,我有一个按钮[submit]来启动长异步请求.[submit]处理程序返回Future.接下来,按钮[submit]被按钮[cancel]替换,以允许取消整个操作.在[取消]处理程序中,我想取消长操作.如何取消提交处理程序返回的Future?我发现没有办法做到这一点.
vov*_*ost 17
您可以使用CancelableOperation或CancelableCompleter取消将来。请参阅以下2个版本:
CancelableOperation包含在测试中,您可以自己尝试):test("CancelableOperation with future", () async {
var cancellableOperation = CancelableOperation.fromFuture(
Future.value('future result'),
onCancel: () => {debugPrint('onCancel')},
);
// cancellableOperation.cancel();
cancellableOperation.value.then((value) => {
debugPrint('then: $value'),
});
cancellableOperation.value.whenComplete(() => {
debugPrint('onDone'),
});
});
test("CancelableOperation with stream", () async {
var cancellableOperation = CancelableOperation.fromFuture(
Future.value('future result'),
onCancel: () => {debugPrint('onCancel')},
);
// cancellableOperation.cancel();
cancellableOperation.asStream().listen(
(value) => { debugPrint('value: $value') },
onDone: () => { debugPrint('onDone') },
);
});
Run Code Online (Sandbox Code Playgroud)
以上两个测试将输出:
then: future result
onDone
Run Code Online (Sandbox Code Playgroud)
现在,如果我们取消注释,cancellableOperation.cancel();则以上两个测试将输出:
onCancel
Run Code Online (Sandbox Code Playgroud)
CancelableCompleter如果您需要更多控制权)test("CancelableCompleter is cancelled", () async {
CancelableCompleter completer = CancelableCompleter(onCancel: () {
print('onCancel');
});
// completer.operation.cancel();
completer.complete(Future.value('future result'));
print('isCanceled: ${completer.isCanceled}');
print('isCompleted: ${completer.isCompleted}');
completer.operation.value.then((value) => {
print('then: $value'),
});
completer.operation.value.whenComplete(() => {
print('onDone'),
});
});
Run Code Online (Sandbox Code Playgroud)
输出:
isCanceled: false
isCompleted: true
then: future result
onDone
Run Code Online (Sandbox Code Playgroud)
现在,如果我们取消注释,cancellableOperation.cancel();我们将得到输出:
onCancel
isCanceled: true
isCompleted: true
Run Code Online (Sandbox Code Playgroud)
请注意,如果使用await cancellableOperation.value或,await completer.operation则它将永远不会返回结果,并且如果操作被取消,它将无限期地等待。这是因为await cancellableOperation.value与写入相同,cancellableOperation.value.then(...)但是then()如果操作被取消则永远不会调用。
And*_*eev 15
Future.delayed一个简单的方法是Timer改用:)
Timer _timer;
void _schedule() {
_timer = Timer(Duration(seconds: 2), () {
print('Do something after delay');
});
}
@override
void dispose() {
super.dispose();
_timer?.cancel();
}
Run Code Online (Sandbox Code Playgroud)
对于那些试图在 Flutter 中实现这一点的人,这里是相同的简单示例。
class MyPage extends StatelessWidget {
final CancelableCompleter<bool> _completer = CancelableCompleter(onCancel: () => false);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Future")),
body: Column(
children: <Widget>[
RaisedButton(
child: Text("Submit"),
onPressed: () async {
// it is true only if the future got completed
bool _isFutureCompleted = await _submit();
},
),
RaisedButton(child: Text("Cancel"), onPressed: _cancel),
],
),
);
}
Future<bool> _submit() async {
_completer.complete(Future.value(_solve()));
return _completer.operation.value;
}
// This is just a simple method that will finish the future in 5 seconds
Future<bool> _solve() async {
return await Future.delayed(Duration(seconds: 5), () => true);
}
void _cancel() async {
var value = await _completer.operation.cancel();
// if we stopped the future, we get false
assert(value == false);
}
}
Run Code Online (Sandbox Code Playgroud)
我完成“取消”预定执行的一种方法是使用Timer. 在这种情况下,我实际上是在推迟它。:)
Timer _runJustOnceAtTheEnd;
void runMultipleTimes() {
_runJustOnceAtTheEnd?.cancel();
_runJustOnceAtTheEnd = null;
// do your processing
_runJustOnceAtTheEnd = Timer(Duration(seconds: 1), onceAtTheEndOfTheBatch);
}
void onceAtTheEndOfTheBatch() {
print("just once at the end of a batch!");
}
runMultipleTimes();
runMultipleTimes();
runMultipleTimes();
runMultipleTimes();
// will print 'just once at the end of a batch' one second after last execution
Run Code Online (Sandbox Code Playgroud)
该runMultipleTimes()方法将按顺序多次调用,但仅在批处理的 1 秒后onceAtTheEndOfTheBatch才会执行。
我的2分钱值...
class CancelableFuture {
bool cancelled = false;
CancelableFuture(Duration duration, void Function() callback) {
Future<void>.delayed(duration, () {
if (!cancelled) {
callback();
}
});
}
void cancel() {
cancelled = true;
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,没有办法取消未来。但是有一种取消Stream订阅的方法,也许可以为您提供帮助。
调用onSubmit按钮将返回一个StreamSubscription对象。您可以显式存储该对象,然后调用cancel()它以取消流订阅:
StreamSubscription subscription = someDOMElement.onSubmit.listen((data) {
// you code here
if (someCondition == true) {
subscription.cancel();
}
});
Run Code Online (Sandbox Code Playgroud)
稍后,作为对某些用户操作的响应,您可以取消订阅:
| 归档时间: |
|
| 查看次数: |
4542 次 |
| 最近记录: |