flutter - 取消 future 超时的优雅方式

标签 flutter dart

在这些情况下,我需要尝试某事一段时间或多次,但不会太久。 Future.timeout 属性看起来是一个自然的选择。我了解到,原始的 Future 即使在超时后仍继续运行,例如:

  Future<void> trySomething() async {
    while (true) {
      print('trying something...');
      bool successful = false; // exit if done
      if (successful) {
        return;
      }
      await Future.delayed(const Duration(seconds: 1));
    }
  }

  trySomething().timeout(const Duration(seconds: 10), onTimeout: () {
    print('try something else...');
  });


以上代码产生以下输出:

I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): try something else...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...

我不太优雅的解决方法是使用外部标志变量向 main future 中的进程指示不再需要其服务:

  bool youAreTooLate = false;
  Future<void> trySomething() async {
    while (true) {
      if (youAreTooLate) {
        return;
      }
      print('trying something...');
      bool successful = false; // exit if done
      if (successful) {
        return;
      }
      await Future.delayed(const Duration(seconds: 1));
    }
  }


  trySomething().timeout(const Duration(seconds: 10), onTimeout: () {
    youAreTooLate = true;
    print('try something else...');
  });

这产生了下面的预期结果,但并没有让我内心变得那么温暖和模糊。

I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): trying something...
I/flutter (26426): try something else...

有没有更好的方法来处理这种情况?

最佳答案

如果您只是想重复做一些有延迟的事情,您可以使用 Timer 来实现这一点,同时保持取消它的能力。

final timer = Timer.periodic(const Duration(seconds: 1), (t) {
  // Do repeated work here.

  if (shouldCancel) {
    // This is the 'timer' object.
    t.cancel();
  }
});

Future.delayed(const Duration(seconds: 10)).then((_) => timer.cancel());

如果您希望真正等待计时器内部的工作完成后再重试,您可以这样做:

Timer timer;

doWork() async {
  // Do your work here.
  // ...

  if (retry) {
    timer = Timer(const Duration(seconds: 1), doWork);
  }
}

Future.delayed(const Duration(seconds: 10)).then((_) => timer?.cancel());

这应该可行,但如果您已经有一个未完成的 Future,则无法实际取消它。

关于flutter - 取消 future 超时的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59673144/

相关文章:

flutter - CERTIFICATE_VERIFY_FAILED 虽然它应该是有效的?

graphics - 是否有大量使用硬件加速的 Dart 图形库?

flutter - 为什么可以将 `int Function()` 类型的回调作为 `void Function()` 传递(例如,对于 Flutter setState)?

Flutter - 滚动时如何使一行停留在屏幕顶部

java - com.deliveryrunner.vendor.MainActivity 无法转换为 android.app.Application

io - 以字节为单位读取目录

ios - 无法直接打开whatsapp聊天群邀请

android - 如何在 flutter 上使用 android 的应用程序包?

firebase - 嵌套的forEach从Firebase检索子集合

flutter - 按下后退按钮时如何在后台发送应用程序