Thursday, September 5, 2013

You complete me, unless you already have a Dart future

Dart Protip: if you already have an instance of Future, you probably don't need a Completer. Simply return the last Future.



If you find yourself using Completers inside of Futures, like this:


  // NOT recommended.

  Future doStuff() {
    Future future = someAsyncProcess();
    Completer completer = new Completer();

    future.then((msg) {
      bool result = msg.result as bool;

      completer.complete(result);
    });

    return completer.future;
  }


then I'm happy to report there's a better way. Dart's Futures chain, so you can do this instead:


  // Recommend.
  Future doStuff() {
    return someAsyncProcess().then((msg) => msg.result);
  }


The last Future in a chain can return another Future, or simply a value. It's always a good idea to return a Future from a function that uses a Future. This way, the caller knows when the method finished its async work, and can properly handle potential errors.

Completers are great for bridging a callback-based API with a Future-based API. For example, suppose your database driver doesn't use Futures, but you need to return a Future. Try this code:

  // A good use of a Completer.

  Future doStuff() {
    Completer completer = new Completer();
    runDatabaseQuery(sql, (results) {
      completer.complete(results);
    });
    return completer.future;
  }

To learn more about Futures, read Using Future Based APIs. To step up your game, read Futures and Error Handling.

Enjoy!
Post a Comment

Disclaimer

I'm probably required to say that the views expressed in this blog are my own, and do not necessarily reflect those of my employer. Also, except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the BSD License.