# 异常处理

# 心法口诀

​ 同步的异常同步做,

​ 异步的异常异步做,

​ 未处理的异常runZoned做,

# 同步异常

与其它语言一样,dart提供类try/catch来来接异常信息,防止未处理的异常而导致后面的代码无法正常运行。

try {
  throw 'sync error';
} catch (e) {
  print(e);
}
1
2
3
4
5

# 异步异常

​ 异步异常指Future中的异常,Future是一个事件循环循环对象,该对象的异常是通过catchError回调来拦截的,如果要使用try/catce的方式拦击,需要将Future变成一个同步对象,变成同步对象很简单,只要await Future就可以了。

//获取Future异常
Future(() {
    throw 'error';
}).catchError((e){
    print(e);
});
//也可以通过try/catch获取异常
try {
    await Future(() {
        throw 'error';
    });
} catch (e) {
    print(e);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

### 全局异常runZoned

​ runZoned直译过来是运行区域的意思,它有什么用呢?这里我们可以将它作为代码区域异常全局处理程序,当然除了全局异常处理之外还有其它的功能。

​ 使用runZoned很简单,它的接收一个匿名函数,也就是它包裹了这个匿名的函数的执行范围,另外通过onError参数我们可以指定一个错误处理函数,当匿名函数内存在未处理的异常时,该错误处理函数就会拦截这个异常。

// 全局函数异常
runZoned(() {
	throw 'error';
}, onError: (e) {
    print('global handler error');
});
// 匿名函数自己处理异常
runZoned(() {
    try {
        throw 'error';
    } catch (e) {
        print("self handler error");
    }
}, onError: (e) {
    print('global handler error');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

下面一个Future的例子,加深你对Future的理解

runZoned(() async{
    try {
        Future.error('error');
    } catch (e) {
        print("self handler error");
    }
}, onError: (e) {
    print('global handler error');
});
// 执行结果:global handler error
runZoned(() async{
    try {
        //同步时需要放在try/catch中执行
        await Future.error('error');
    } catch (e) {
        print("self handler error");
    }
}, onError: (e) {
    print('global handler error');
});
// 执行结果:self handler error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

下面看一个Stream的例子

runZoned(() async {
    Stream.error('error').listen((data) {
        print(data);
    }, onError: (e) {
        print('self handler error');
    });
}, onError: (e) {
    print('global handler error');
});
//await for的方式监听stream时会导致异常
//这是因为stream每次返回一个Future对象,
//实际await等待的是data即:await data,for只是遍历Stream对象
runZoned(() async {
	await for (var data in Stream.error('error')) {}
}, onError: (e) {
    print('global handler error');
});
runZoned(() async {
    try {
        await for (var data in Stream.error('error')) {}
    } catch (e) {
        print('self handler error');
    }
}, onError: (e) {
    print('global handler error');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28