dart 防抖和节流

·  阅读 1595

前端的开发者都或多或少的遇到过节流与防抖的问题。函数节流和函数防抖,两者都是优化执行代码效率的一种手段。在一定时间内,代码执行的次数不一定是越多越好。相反,频繁的触发或者执行代码,会造成大量的重绘等问题,影响浏览器或者机器资源。因此把代码的执行次数控制在合理的范围。既能节省浏览器 CPU 资源,又能让页面浏览更加顺畅,不会因为 js 的执行而发生卡顿。这就是函数节流和函数防抖要做的事。

flutter 也同样有此场景。

防抖(debounce)

防抖在生活中随处可见,毕竟经典的就是电梯,当没人进出电梯的时候,过一段时间它就会自动关上,而如果在它关上之前有人按了开门或者进出电梯,那么电梯关门时间又会重新计时。

在代码里,触发事件时,不立即执行目标操作,而是给出一个延迟的时间,在该时间范围内如果再次触发了事件,则重置延迟时间,直到延迟时间结束才会执行目标操作。

示例

如设定延迟时间为 500ms,

如果在 500ms 内没有再次触发事件,则执行目标操作 如果在 500ms 内再次触发了事件,则重置延迟时间,重新开始 500ms 的延迟,直到 500ms 结束执行目标操作

效果

连续点击防抖按钮,停止点击时才会执行"debounceCount++"操作,只会执行一次操作

示例图

代码

TextButton.icon(
    icon: Icon(Icons.add),
    label: Text('防抖:$debounceCount'),
    onPressed: debounce(() {
      if (!mounted) {
        return;
      }
      setState(() {
        debounceCount++;
      });
    }),
);

复制代码
  /// 函数防抖
  ///
  /// [func]: 要执行的方法
  /// [delay]: 要迟延的时长
  void Function() debounce(
    Function func, [
    Duration delay = const Duration(milliseconds: 500),
  ]) {
    Timer? timer;
    void Function() target = () {
      timer?.cancel();
      timer = Timer(delay, () {
        func.call();
      });
    };
    return target;
  }
复制代码
/// 也可以采用类的方式
class Debouncer {
  final Duration? delay;
  Timer? _timer;

  Debouncer({this.delay});

  void call(void Function() action) {
    _timer?.cancel();
    _timer = Timer(delay ?? const Duration(milliseconds: 1000), action);
  }
}
复制代码

节流(throttle)

在触发事件时,立即执行目标操作,同时给出一个延迟的时间【也有说是先给出延迟时间再执行的】,在该时间范围内如果再次触发了事件,该次事件会被忽略,直到超过该时间范围后触发事件才会被处理。

示例

如设定延迟时间为 500ms,

如果在 500ms 内再次触发事件,该事件会被忽略 如果 500ms 延迟结束,则事件不会被忽略,触发事件会立即执行目标操作,并再次开启 500ms 延迟

效果

连续点击防抖按钮,在本次操作执行完成前的多次点击会被忽略,只会执行一次"throttleCount++"操作。

TextButton.icon(
    icon: Icon(Icons.add),
    label: Text('节流:$throttleCount'),
    onPressed: throttle(() {
      if (!mounted) {
        return;
      }
      setState(() {
        throttleCount++;
      });
    }) as void Function()?,
);

复制代码
  /// 节流
  ///
  /// [func]: 要执行的方法
  /// [delay]: 要迟延的时长
  Function throttle(
    Function func, [
    Duration delay = const Duration(milliseconds: 500),
  ]) {
    Timer? timer;
    return () {
      if (timer != null) return;
      timer = Timer(delay, () {
        func.call();
      });
    };
  }

复制代码
class Throttle {
  final Duration delay;
  Timer? timer;

  Throttle({this.delay = const Duration(milliseconds: 500)});

  void call(Function callBack) {
    if (timer != null) return;
    timer = Timer(delay, () {
      callBack.call();
    });
  }
}
复制代码
复制代码
分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改