Dart里Future的错误处理有点绕,官方的guide在:https://www.dartlang.org/articles/futures-and-error-handling/

这里最容易造成的误解在于,当你自己创建一个返回Future的函数的时候,在该函数内的逻辑处理需要自己处理Exception。说起来有点抽象,可以看下代码。举例来说:

[codesyntax lang="php"]

  Future doItWithFuture() {
    var e = new Exception('error!!!');
    throw e;
    return new Future.value(123);
  }

  void handleError(e) {
    print(e);
  }

  doItWithFuture()
  .then((_) {
    print('normal end');
  })
  .catchError(handleError);

[/codesyntax]

你可以猜下,运行的结果是什么,结果是:

Unhandled exception:
Exception: error!!!

程序崩溃了。

这里我们需要注意的是官方guide里的一句话:

The registered callbacks fire based on the following rules: then()’s callback fires if it is invoked on a Future that completes with a value; catchError()’s callback fires if it is invoked on a Future that completes with an error.

这里的关键在于粗体的那段 ,也就是说,你在写返回Future的函数的时候,必须自己处理好内部的错误,即便有错误,也需要返回Future,只不过这里的Future是一个承载错误的Future。

看范例:

[codesyntax lang="php"]

  Future doItWithFuture() {
    var e = new Exception('error!!!');
    return new Future.error(e);
  }

  void handleError(e) {
    print(e);
  }

  doItWithFuture()
  .then((_) {
    print('normal end');
  })
  .catchError(handleError);

[/codesyntax]

运行结果一切正常,打印:

Exception: error!!!

这里有点小绕,所以留个笔记。

最后附带一个使用Completer的范例:

[codesyntax lang="php"]

  Future doItWithFuture() {
    final completer = new Completer();

    var e = new Exception('error!!!');
    completer.completeError(e);

    return completer.future;
  }

  void handleError(e) {
    print(e);
  }

  doItWithFuture()
  .then((_) {
    print('normal end');
  })
  .catchError(handleError);

[/codesyntax]