如何在我的代码中等待来自其他地方的异步链的最终结果?

Posted

技术标签:

【中文标题】如何在我的代码中等待来自其他地方的异步链的最终结果?【英文标题】:How do I await end result of async chain from elsewhere in my code? 【发布时间】:2019-06-12 04:01:17 【问题描述】:

Flutter 新手在这里。我正在尝试在 dart 中解析一些 json,并且对读取底层文件的异步性质感到困惑。

我如何等到 json 完成解析而不仅仅是底层文件?我的困惑是读取文件是异步的,但解析 json 是同步的。现在我知道您可以使用 await 来等待 Future 完成读取文件时 loadString 返回的内容。但是我该如何“等待”解析 json 的完成呢?

jsonDecode 不接受 Future 作为其参数,并且它同步运行,因此我无法将其结果包装到 Future 中(或者我可以吗?)。如果我能以某种方式得到一个 Future _string2Item;作为json解析操作的结果,我认为这将解决我的问题,因为我可以简单地:在做任何事情之前等待_string2Item。

class ItemsRepository

 Map<String, Item> _string2Item;

  //This does not work unfortunately. However, I don't want to return an instance that hasn't finished parsing the json
  ItemsRepository() async
  
    await init();
  

  Future<String> _loadFile() async 
    return await rootBundle.loadString('assets/data/item_int2string.json');
  

  Future<void> init() async
  
    var _fileContents = _loadFile();
    _string2Item = jsonDecode(await _fileContents);
  

  Item getItem(String id)
  
    return _string2Item[id];
  


//... somewhere else in my code
ItemRepository ir = ItemRepository();
ir.getItem("42"); //this crashes because _string2Item hasn't finished parsing yet.

感谢任何帮助。

【问题讨论】:

【参考方案1】:

用途:

ItemRepository ir = ItemRepository();
await ir.init();
ir.getItem('42');

您的课程可以更简洁地写成:

class ItemsRepository 
  Map<String, Item> _string2Item;

  Future<void> init() async 
    _string2Item = jsonDecode(
        await rootBundle.loadString('assets/data/item_int2string.json'));
  

  Item getItem(String id) => _string2Item[id];

您可以删除整个类并用函数替换它:

Future<Map<String, Item>> getItems() async => jsonDecode(
      await rootBundle.loadString('assets/data/item_int2string.json'),
    );   

并像这样使用它

  Map<String, Item> items = await getItems();
  print(items['42']);

【讨论】:

有没有办法避免额外的 init 调用并在构造函数中完成?另外,有没有办法以某种方式将 _string2Item 声明为 Future > 以便我可以在其他地方检查是否完成? 构造函数(甚至工厂构造函数)可能不是异步的,所以,不是。由于 ItemsRepository 类似乎不再做任何事情,您可以用一个简单的***函数替换它 - 请参阅更新的答案。 好的。关于我的第二个问题。是否可以将 _string2Item 声明为在 init() 完成后完成的 Future >?这样我就可以拥有多个监听器,它们都在等待未来的完成并自动恢复。我正在考虑多线程的发布-订阅模式或 wait()/notify()。 Future 不能有多个服务员。 Flutter 的替代方案是广播流(如在 BLoC 模式中使用的那样)或InheritedWidget,它提供 null(或其他虚拟值),直到值可用并且之后的值。

以上是关于如何在我的代码中等待来自其他地方的异步链的最终结果?的主要内容,如果未能解决你的问题,请参考以下文章

等待从其他地方调用的函数的结果

JavaScript异步/等待:等待后代码不会继续[重复]

如何在 ASP.NET 中等待异步 Web 服务调用的结果以获得最佳性能

如何等待来自 for 循环的多个异步调用?

如何从 Django 发送异步 HTTP 请求并在 python2.7 中等待结果?

等待先前的异步功能完成[重复]