How to handle errors coming back from Futures when I am not awaiting the Future?

44 Views Asked by At

I have something like this:

Future<void> f1() { ... }
Future<void> f2() { ... }
Future<void> f3() { ... }

void main() async
{
  f1();
  f2(); // might throw an Exception

  await f3();
}

Note - I am deliberately not awaiting f1 or f2, I am only awaiting the consequences in f3.

How do I handle the possibility of an exception in f2 ? The normal try / catch procedure doesn't work.

I have seen some discussion of catchError but I don't really understand it.

I would like to do the equivalent of:

Future<void> f1() { ... }
Future<void> f2() { ... }
Future<void> f3() { ... }

void main() async
{
  f1();
  try 
  {
    f2(); // might throw an Exception
  }
  on MyException catch( e )
  {
    print('this is what I expected to happen, so carry on regardless');
  }

  await f3();
}
2

There are 2 best solutions below

4
jamesdlin On

As you noted, you can use Future.catchError:

void main() async {
  f1();
  f2().catchError(
    (e) => print('this is what I expected to happen, so carry on regardless'),
    test: (e) => e is MyException,
  );

  await f3();
}

Note that Future.catchError can be tricky to use. You always can wrap your Future in another function that internally uses await with try-catch, and then the caller doesn't need to use await:

void main() async {
  f1();

  void ignoreFailure(Future<void> future) async {
    try {
      await future;
    } on MyException catch (e) {
      print('this is what I expected to happen, so carry on regardless');
    }
  }

  ignoreFailure(f2());

  await f3();
}

If you don't need to do any handling for the error and want to ignore all failures, you also can use the ignore extension method on Futures:

void main() async {
  f1();
  f2().ignore();

  await f3();
}
1
Adam Rose On
test('repeated NBA', () async {
  bool fired = false;

  runZonedGuarded( () async {
    Signal s2 = Signal();

    s2.nba( 2 );
    s2.nba( 2 );
    s2.nba( 3 );
  },
  (error, stackTrace) {
    print('Seen expected error: $error');
    fired = true;
  } );

  await Future.delayed( Duration.zero );
  expect( fired , true );
});