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

时间:2019-01-17 21:35:27

标签: dart async-await 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 个答案:

答案 0 :(得分: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']);