【问题标题】:Return multiple results from an async method?从异步方法返回多个结果?
【发布时间】:2019-10-08 18:29:44
【问题描述】:

我目前有一个看起来像这样的方法:

typedef void MyCallback(int status, String body);


void makeRequest(String url, MyCallback callback) async {
  if( someCondition ){
    callback(1, '');
  }

  Response response = await http.get(url);

  if( response.httpCode == 200 ){
    callback(2, response.body);
  }
  else{
    callback(3, '');
  }
}

我想摆脱回调,以便等待makeRequest 的结果。但如果我只是让它返回一个Future,我将无法返回不止一次。

我研究过使用流,但它似乎有点复杂。所以基本上我正在寻找像Future 这样方便的东西,但它可能会收到“部分结果”,即不止一次收到结果。举例说明:

MultiFuture<int> makeRequest(String url){
  MultiFuture result = new MultiFuture();

  if( someCondition ){
    result.value(1);
  }

  http.get(url).then((response){
    if( response.httpCode == 200 ){
      result.value(2);
    }
    else{
      result.value(3);
    }

    result.finish();
  });


  return result;
}




MultiFuture requestResult = makeRequest('https://example.com');

await requestResult.onValue((int value){
  print('value: $value');
});      
// When result.finish() is called, the await is finished

使用流是我的最佳选择,还是有某种我不知道的MultiFuture?

【问题讨论】:

  • 您只是在描述流。是的,它们比期货稍微复杂一点,但它们完全符合您的用例并且是用语言烘焙的。所以只需标记您的方法async* 并开始yield 结果;)。

标签: flutter dart dart-async


【解决方案1】:

从异步方法返回多个结果正是流的作用。这是我根据您的代码制作的示例,以便您更容易理解它的工作原理:

class MultiFuture {
  StreamController<int> _resultController = StreamController<int>();
  Stream<int> get requestResult => _resultController.stream;

  void makeRequest(String request) async {
    if (true) {
      _resultController.sink.add(1);
    }

    // mock request
    await Future.delayed(Duration(seconds: 3));

    if (true) {
      _resultController.sink.add(2);
    } else {
      _resultController.sink.add(3);
    }
  }

  void example() {
    makeRequest("https://example.com");

    requestResult.listen((value) {
      print('value: $value');
    });
  }
}

您可以调用 MultiFuture().example(); 对其进行测试;


但我建议您观看这些简单的短片以获得更好的想法: Async Coding With Dart

【讨论】:

  • 谢谢!我现在没有时间对此进行测试,但似乎缺少await 一些最终值或关闭事件的能力,比如我的伪代码中的.finish()?
  • 每次调用_resultController.sink.add 都会触发requestResult.listen,这就是为什么您不需要等待某个最终值或关闭事件的原因。尝试使用此代码在任何地方添加打印,还可以查看非常简单且解释清楚的视频。 P.S. 退出屏幕需要关闭的是控制器,应该在widget状态的dispose()方法里面调用resultController.close()来释放资源
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 1970-01-01
  • 2018-09-01
  • 2012-02-14
  • 1970-01-01
相关资源
最近更新 更多