如何在 Dart 中使用 async* 函数

How to work with async* functions in Dart

我正在使用 flutter_bloc 库。

在 bloc 中,mapEventToState 方法是一个 async* 函数,returns Stream<BlocState>。 从这个函数我调用其他 async* 函数,像这样 yield* _handleEvent(event)

在这种方法中,我正在调用一些 Future returns 函数,但在 Future then() 函数中它不会让我调用其他 yield* 函数。

这是一个例子:

Stream<BlocState> mapEventToState(BlocEvent event) async*{
     yield* _handlesEvent(event); //This calls to worker method 
}

Stream<BlocState> _handleEvent(BlocEvent event) async* {
   _repository.getData(event.id).then((response) async* { //Calling Future returned function
         yield* _processResult(response); //This won't work
     }).catchError((e)  async* {
         yield* _handleError(e);  //This won't work either
     });

   Response response = await _repository.getData(event.id); //This do works but I want to use it like above, is it possible?
   yield* _processResult(response); //This do works
}

但是问题是,如何在dart中结合Future和Stream。 我可以使用有效的 await _repository.getData。但是我不会发现错误。

尝试使用 try-catch 块。它适用于等待操作。

  1. await只是.then()的语法糖,把await放在try-catch块中是语法糖使用 .catchError。您可以用一种方式完成的事情可以用另一种方式完成。

  2. 在您使用 .then()/.catchError() 的第一个版本中,您的函数没有 return 任何东西。

  3. 您的回调将无法工作,因为您在其中使用了 yield*,但您没有使用 sync*async* 指定回调。为避免名称冲突,yield 关键字需要它们(就像 await 需要使用 asyncasync* 的函数一样)。

这是一个可以与 .then().catchError() 一起使用的版本:

Stream<BlocState> _handleEvent(BlocEvent event) async* {
  yield* await _repository.getData(event.id).then((response) async* {
    yield* _processResult(response);
  }).catchError((e) async* {
    yield* _handleError(e);
  });
}

注意回调不需要使用yield*;他们可以 return 他们的 Stream 直接:

Stream<BlocState> _handleEvent(BlocEvent event) async* {
  yield* await _repository.getData(event.id).then((response) {
    return _processResult(response);
  }).catchError((e) {
    return _handleError(e);
  });
}

但是(正如其他人所指出的)使用 await 而不是 Future API 简化了整个事情(特别是因为我们已经在使用 await ):

Stream<BlocState> _handleEvent(BlocEvent event) async* {
  try 
    response = await _repository.getData(event.id);
    yield* _processResult(response);
  } catch (e) {
    yield* _handleError(e);
  }
}

有关可运行示例,请参阅 https://dartpad.dartlang.org/fc1ff92e461754bdb35b998e7fbb3406

要处理异步函数中的错误,请使用 try-catch:

try {
  Response response = await _repository.getData(event.id)
} catch (err) {
  print('Caught error: $err');
}