DEV Community

Mattia Pispisa
Mattia Pispisa

Posted on

Expand your Future, extensions in Dart

Extend a class

In Dart, you can extend a class to add new class or instance methods.

extension FutureDelayed on Future {
 Future<T> delayed(int milliseconds) {
    return this.then((value) => Future.delayed(Duration(milliseconds: milliseconds), () => value));
  }}

void main() {
  Future<int> futureValue = Future.value(42).delayed(2000);

  futureValue.then((value) {
    print("here after 2 sec!");
  });
}
Enter fullscreen mode Exit fullscreen mode

Extend an async function

In Dart, you can do something even more special!

You can extend functions, and if these functions are asynchronous, you can create something truly remarkable.

Let's dive into some practical and simple demonstrative examples.

retry future

/// This extension enables us to create new methods 
/// for a function that takes a "remainingTimes" parameter 
/// as input and returns a Future with a generic T.
extension Retry<T> on Future<T> Function(int remainingTimes) {
  Future<T> retry(int count) async {
    while (true) {
      try {
        final result = await this(count);
        return result;
      } catch (e) {
        if (count > 0) {
          count--;
        } else {
          rethrow;
        }
      }
    }
  }
}

void main() {
 // wrap "asyncFunc" in an anonymous function 
 // that receive an input "remain" (this(count) written above in "retry")

 // asyncFunc will be retried up to a maximum of 3 times 
 // in case of an error. 
 ((remain) => asyncFunc()).retry(3)
}
Enter fullscreen mode Exit fullscreen mode

count elapsed time

/// This extension enables us to create new methods 
/// for a function without parameters 
/// and returns a Future with a generic T.
extension FutureMeasure<T> on Future<T> Function() {

  Future<T> measure() async {
    Stopwatch stopwatch = Stopwatch()..start();
    try {
      final result = await this();
      return result;
    } catch (e) {
      rethrow;
    } finally {
      stopwatch.stop();
      print(stopwatch.elapsedMilliseconds);
    }
  }
}

void main() {
 // wrap "asyncFunc" in an anonymous function 
 // without parameter

 // will print the elapsed asyncFunc time
 (() => asyncFunc()).measure()
}
Enter fullscreen mode Exit fullscreen mode

This way, it's easy to understand how to create your own extensions that enhance asynchronous functions with specific capabilities tailored for your app.

Top comments (0)