【问题标题】:Throttle function execution in dartdart 中的节流函数执行
【发布时间】:2019-04-05 10:14:16
【问题描述】:

Dart 有没有办法像这样限制函数执行

Observable.throttle(myFunction,2000);

【问题讨论】:

  • thottledebounce from github.com/ReactiveX/rxdart 应该提供。 medium.com/fantageek/… 可能是相关的。
  • 我不确定如何将这些信息与我所拥有的信息结合起来,听按钮是否对颤振有效?
  • 在 Dart 中,要重复调用的函数通常是 Stream 上的侦听器 - 你在这里有 Stream 并且你试图限制传递给 @ 的函数987654330@?如果是这种情况,我们应该将其视为限制流而不是函数。为此使用values.transform(throttle(Duration(seconds: 2))).listen(myFunction)pub.dartlang.org/packages/stream_transform 如果这不是 Stream 侦听器,您能否详细说明用例?你需要Function 可以作为参数传递吗?
  • 我想限制函数执行,例如假设有一个按钮将向 api 发送请求,我希望该按钮始终可点击,但每次调用 1 次都会限制 api 调用例如 1 分钟,因此用户可以随意点击,但我每分钟只会发送一个请求。
  • 您可以使用 StreamController 将函数调用转换为 Stream。 Mayberxdart Observable 提供了一些开箱即用的东西来做到这一点。

标签: dart flutter throttling rxdart


【解决方案1】:

使用https://pub.dartlang.org/documentation/rxdart/latest/rx/Observable/throttle.html

因此,您在 Dart 2 中使用 RxDart 的示例是

final subject = new ReplaySubject<int>();
myCaller(Event event) {
  subject.add(event);
}
subject
  .throttle(Duration(seconds: 2))
  .listen(myHandler);

【讨论】:

    【解决方案2】:
    // you can run the code in dartpad: https://dartpad.dev/
    typedef VoidCallback = dynamic Function();
    
    class Throttler {
      Throttler({this.throttleGapInMillis});
    
      final int throttleGapInMillis;
    
      int lastActionTime;
    
      void run(VoidCallback action) {
        if (lastActionTime == null) {
          action();
          lastActionTime = DateTime.now().millisecondsSinceEpoch;
        } else {
          if (DateTime.now().millisecondsSinceEpoch - lastActionTime > (throttleGapInMillis ?? 500)) {
            action();
            lastActionTime = DateTime.now().millisecondsSinceEpoch;
          }
        }
      }
    }
    
    void main() {
      var throttler = Throttler();
      // var throttler = Throttler(throttleGapInMillis: 1000);
      throttler.run(() {
        print("will print");
      });
      throttler.run(() {
        print("will not print");
      });
      Future.delayed(Duration(milliseconds: 500), () {
        throttler.run(() {
          print("will print with delay");
        });
      });
    }
    

    【讨论】:

    • static int lastActionTime; 所以,如果你使用Throttler 类的多个实例,它们都将共享相同的lastActionTime
    • 你是对的。我犯了一个错误。我顺便编辑一下答案。
    【解决方案3】:

    按照 Günter Zöchbauer 的思路,您可以使用 StreamController 将函数调用转换为 Stream。举例来说,假设myFunction 有一个int 返回值和一个int 参数。

    import 'package:rxdart/rxdart.dart';
    
    // This is just a setup for the example
    Stream<int> timedMyFunction(Duration interval) {
      StreamController<int> controller;
      Timer timer;
      int counter = 0;
    
      void tick(_) {
        counter++;
        controller.add(myFunction(counter)); // Calling myFunction here
      }
    
      void startTimer() {
        timer = Timer.periodic(interval, tick);
      }
    
      void stopTimer() {
        if (timer != null) {
          timer.cancel();
          timer = null;
        }
      }
    
      controller = StreamController<int>(
          onListen: startTimer,
          onPause: stopTimer,
          onResume: startTimer,
          onCancel: stopTimer);
    
      return controller.stream;
    }
    
    // Setting up a stream firing twice a second of the values of myFunction
    var rapidStream = timedMyFunction(const Duration(milliseconds: 500));
    
    // Throttling the stream to once in every two seconds
    var throttledStream = rapidStream.throttleTime(Duration(seconds: 2)).listen(myHandler);
    

    【讨论】:

      【解决方案4】:
      import 'package:flutter/foundation.dart';
      import 'dart:async';
      
      // A simple class for throttling functions execution
      class Throttler {
        @visibleForTesting
        final int milliseconds;
      
        @visibleForTesting
        Timer? timer;
      
        @visibleForTesting
        static const kDefaultDelay = 2000;
      
        Throttler({this.milliseconds = kDefaultDelay});
      
        void run(VoidCallback action) {
          if (timer?.isActive ?? false) return;
      
          timer?.cancel();
          action();
          timer = Timer(Duration(milliseconds: milliseconds), () {});
        }
      
        void dispose() {
          timer?.cancel();
        }
      }
      
      // How to use
      void main() {
        var throttler = Throttler();
      
        throttler.run(() {
          print("will print");
        });
        throttler.run(() {
          print("will not print");
        });
        Future.delayed(const Duration(milliseconds: 2000), () {
          throttler.run(() {
            print("will print with delay");
          });
        });
      
        throttler.dispose();
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-04
        • 2021-09-30
        • 2020-11-14
        • 1970-01-01
        • 2019-05-31
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 2021-10-19
        相关资源
        最近更新 更多