【问题标题】:Dart callback - passing asynchronous message to parent objectDart 回调 - 将异步消息传递给父对象
【发布时间】:2024-01-19 12:22:01
【问题描述】:

我正在尝试通过父类提供的回调函数(ondone)从子类传递数据(bool),该回调函数将定期调用带有布尔参数的函数。

import 'dart:async';

class Flow {
  MyTimer timer;
  bool done = false;
  Function ondone;

  Flow() {
    ondone = (bool b) => done=b;
  }

  void addtimer(int t) {
    timer = MyTimer(t, ondone);
  }

}

class MyTimer {
  final int time;
  int remaining;
  Function callback;
  Timer _timer;

  MyTimer(this.time, this.callback){
    remaining = time;
  }

  void run() {
    _timer = Timer.periodic(
        Duration(seconds: 1), 
        (t) { 
          remaining--;
          if (remaining == 0) {
          _timer.cancel();
          callback(true);
    }
    });
  }
}

但我无法确定是否调用了回调,因为打印函数(在 main 中)没有打印任何包装在 if 表达式中的内容。

void main() {
  var flow=Flow();
  flow.addtimer(5);
  flow.timer.run();
  if(flow.done) print('Timer Finished..');
  print('I need to run while timer is working');
}

以命令式的方式将数据从孩子传递给父母对我来说很重要(作为初学者)。

【问题讨论】:

  • 您的 Timer.periodic 正在运行 (t) => remaining--。因此,remaining 将继续变小而不会发生任何其他事情,因为您没有运行任何其他代码。
  • 您从main() 拨打run()。然后整个执行此方法,包括if。因此,您正在创建一个Timer,然后立即检查if (remaining == 0),这将是false,因为您将其设置为5
  • 但是在剩余==0 之后如何从 main 运行打印功能

标签: dart timer callback message-passing


【解决方案1】:

flow.timer.run() 的调用会调用异步执行的Timer。您的下一行代码立即测试flow.done,当然它还没有完成。如果你这样做:

  flow.timer.run();
  await Future.delayed(Duration(seconds: 6));
  if (flow.done) print('Timer Finished..');

然后您的 main 函数将暂停 6 秒,此时 Timer 将完成。

如果您确实想等待延迟,您可以编写如下代码:

  Future<void> run() async {
    while (remaining > 0) {
      await Future.delayed(Duration(seconds: 1));
      remaining = remaining - 1;
    }
    callback(true);
  }

并将其称为:

  await flow.timer.run();

编辑:如果你想在main运行其他代码然后等待,你可以这样做:

  var future = flow.timer?.run();
  print('Timer is running...');
  await future;
  if (flow.done) print('Timer Finished..');

【讨论】:

  • 谢谢。现在工作。有没有更好的方法来实现这个没有 Future.delaying 手动
  • 我编辑了答案以显示如何更改 run()。
  • 经验教训。人们需要对他们的异步代码更加深思熟虑。
  • 但是如果我要在 await 调用之后添加更多代码,则 await 会阻塞 main() 函数。有没有不用线程的方法?
  • 我添加了一个示例,main 在等待之前运行其他代码。