在Dart语言中,如何在生成器函数中创建错误同时保持其创建值?
import 'dart:math' show Random;
main() {
sum20RandomNumbers().then((sum) {
print("Sum: $sum");
});
}
Future<double> sum20RandomNumbers() async {
var randomStream = generateRandomNumbers().handleError((error) {
print('Ignore large number: ${error}');
// How can I ignore error here?
});
int count = 0;
double sum = 0;
await for (var n in randomStream) {
print(n);
sum += n;
if (++count >= 20) // sum 20 numbers at most
break;
}
return sum;
}
Stream<double> generateRandomNumbers([int seed]) async* {
final random = Random(seed);
while (true) {
final nextDouble = random.nextDouble();
if (nextDouble > 0.8) {
throw Exception('$nextDouble');
// how can I keep generating next random numbers?
}
yield nextDouble;
}
}
上面的代码显示sum20RandomNumbers()
的意图是精确地累加20个随机数,但是在生成器函数generateRandomNumbers()
中引发异常后,它将停止。抛出错误后如何保持生成器函数产生值?
答案 0 :(得分:1)
对于sync*
函数,您不能这样做。
Iterable
可以报告错误的唯一方法是抛出Iterator
的{{1}}方法。为此,必须抛出moveNext
方法。
抛出sync*
函数时,它将终止函数的主体,这使该主体无法继续并产生更多值。
抛出sync*
的函数也会发生同样的事情,但是在那里您也有不同的发出错误的方式。因为流可以将错误报告为流的一部分,所以有可能发出错误并继续,因此您只能通过 throwing 来做到。
async*
诀窍是Stream<double> generateRandomNumbers([int seed]) async* {
final random = Random(seed);
while (true) {
final nextDouble = random.nextDouble();
if (nextDouble > 0.8) {
yield* Future<double>.error(Exception('$nextDouble')).asStream();
continue;
}
yield nextDouble;
}
}
包含错误的流。您可以通过许多不同的方式来做到这一点。
yield*
或
yield* Future<double>.error(theError).asStream();
或
yield* () async* { throw theError; } ();
在yield* (StreamController<double>()..addError(theError)..close()).stream;
类获得Stream
协整器之前,按流未来是最简单,最易读的方法。