defer<T> function

void defer<T>(
  1. T key,
  2. FutureOr task(
    1. T key
    ), {
  3. Duration min = const Duration(seconds: 1),
  4. Duration? max,
  5. String? category,
})

Defers the execution of a task. If the key is the same, the task in the second invocation will override the previous. In other words, the previous task is canceled.

It is useful if you have a task that happens frequently but you prefer not to execute them all but only the once for a while (because of costly). For example,

defer("cur.task", (key) {
  currentUser.save(["task"]); //a costly operation
}, min: const Duration(seconds: 1), max: const Duration(seconds: 10));
//then, it executes not faster than once per 10s,
//and no later than 100s
  • key - used to identify task. If both category and key are the same, we consider the task is the same. If different, they are handled separately.
  • task - the task. It can return void, null or an instance of Future
  • min - specifies the minimal duration that the given task will be executed. You can't specify null here. Default: 1 second. That is, the task will be invoked min milliseconds later if no following invocation with the same key.
  • max - specifies the maximal duration that the given task will be executed. Default: null. If specified, task will be execute at least max milliseconds later even if there are following invocations with the same key. If not specified, it will keep waiting.

Implementation

void defer<T>(T key, FutureOr task(T key),
    {Duration min = const Duration(seconds: 1), Duration? max,
     String? category}) {
  final dfkey = _DeferKey(key, category),
    di = _defers.remove(dfkey) as _DeferInfo<T>?;
  if (di == null) {
    _defers[dfkey] = _DeferInfo<T>(_startTimer(dfkey, min), task);
  } else {
    _defers[dfkey] = di; //put back; remove-and-add, so dfkey is the last one
    di..timer.cancel()
      ..task = task
      ..timer = _startTimer(dfkey, di.getDelay(min, max));
  }
}