Dart - Future Exception Handling

In Dart, we can define function that returns Future. Since SDK version 1.9, Dart allows us to use async-await that makes the code easier to read. But, if you're still using Future methods chain by using .then() to get the result, here's how to handle error

Basic Error Handling

For example, there is an async function doSomething. There's a another function processResult that will get and processs the result from doSomething if doSomething is not error. However, processResult will not be executed if error occured while executing doSomething. Dart will try to find the nearest catchError method and execute the function. So, if we want to handle error, we need to add Future's catchError method in the chain and pass a function on it for handling error.

  doSomething() async {
    throw 'An error';
  }
  
  processResult(result) {
    print('Result: $result');
  }

  handleError(e) {
    print('Error: ${e.toString()}');
  }
  
  main() async {
    doSomething()
        .then(processResult)
        .catchError(handleError);
  }

Catch Specific Error

Sometimes you may want to handle a specific error differently. To do so, add another catchError that's only executed for that specific error. You need to pass optional argument test whose value is a function that accepts one parameter. If you pass test argument on catchError, it will only handle the error if the test function returns true. Of course you have to catch the specific error first before catchError that handles general error.

  import 'dart:async';
  
  import 'package:http/http.dart' as Http;
  
  doSomething() async {
    throw new TimeoutException("Timeout");
  }
  
  processResult(result) {
    print('Result: $result');
  }
  
  handleTimeoutError(e) {
    print('TimeoutException: ${e.toString()}');
  }
  
  handleError(e) {
    print('Error: ${e.toString()}');
  }
  
  main() async {
    doSomething()
        .then(processResult)
        .catchError(
          handleTimeoutError,
          test: (e) => e is TimeoutException
        )
        .catchError(handleError);
  }

Using Finally

Most of you already familiar with try...catch...finally. The finally block is always executed whether error occurs or not. In Dart's Future, the equivalent to finally is whenComplete.

  main() async {
    doSomething()
        .then(processResult)
        .catchError(handleError)
        .whenComplete(() {
          print('Finish');
        });
  }