Future用来表示将来可能会出现的值或者错误。可以注册回调来处理其返回的值或者错误。例如
Future<int> future = getFuture();
future.then((value) => handleValue(value))
.catchError((error) => handleError(error));
某些时候可以用一个future去接受另外一个future的value或者error 。
Future<int> successor = future.then((int value){
return 42;
}, onError: (e){
if(canHandle(e)){
return 499;
} else {
throw e;
}
});
需要注意的是当一个Future在拥有接收者之前报错的话,则接收者的catchError将捕获不到异常,会被全局的error-handler捕获,目的是防止异常被静默删除。这就意味着错误处理应该提前注册,以便及时处理错误。以下实例就潜在上述问题:
var future = getFuture();
new Timer(Duration(millisecords: 5),(){
//显然如果在5millisecords内报错之后的onError将捕获不到此异常
future.then((value){userValue(vale)},
onError:(e){handleError(e)});
});
通常我们需要给Future注册两个回调来增加其可读性。
Future future = Future(foo);
future.then((value) => handleValue(value)).catchError((e) => handleError(e));
//当然还有这种
Future future = Future(foo);
future.then((value) => handleValue(value),onError(e) => handleError(e));
上述两种写法第一种会catch foo方法的异常以及 handleValue(value)方法的异常。第二种则只关注foo的异常。
特殊场景的try catch
Future<void> foo() async{
throw Exception('1');
}
Future<void> foo1(){
throw Exception('2');
}
Future<void> foo2(){
throw Exception('3');
}
void main() async{
foo().catchError((e) => handleError(e));
foo1().catchError((e) => handleError(e));
try {
await foo2();
} catch (e) {
print(e);
}
}
运行之后或发现foo1()方法中的exception2 是没有被catch住的,这时我们再看catchError的注释 Handles errors emitted by this [Future],翻译过来就是处理由这个Future提交的exception,在不加async的时throw将不会被认定为Future提交的错误,而是一个同步错误。需要像foo2一样使用同步try catch 方式去捕获。为了使得代码可读性提高,如果需要在Future 抛出异常的话,我们应该使用如下的方式:
Future<void> foo3(){
reture Future.error(Exception('4')) ;
}