Как мне ожидать конечного результата асинхронной цепочки из другого места в моем коде? - PullRequest
0 голосов
/ 18 января 2019

Новичок флаттера здесь. Я пытаюсь проанализировать некоторые JSON в дротик, и я путаюсь с асинхронной природой чтения базового файла.

Как мне ждать, пока json закончит анализ, а не только основной файл? Я путаюсь с тем, что чтение файла происходит асинхронно, но синтаксический анализ json является синхронным. Теперь я знаю, что вы можете использовать await, чтобы дождаться завершения Future, которое возвращается loadString при чтении файла. Но как мне тогда «ждать» завершения разбора json?

jsonDecode не принимает 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 голосов
/ 18 января 2019

Использование:

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']);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...