Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dart 我如何在代码的其他地方等待异步链的最终结果?_Dart_Async Await_Flutter - Fatal编程技术网

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

Dart 我如何在代码的其他地方等待异步链的最终结果?,dart,async-await,flutter,Dart,Async Await,Flutter,我是新手。我试图在dart中解析一些json,但对读取底层文件的异步性质感到困惑 如何等待json完成解析,而不仅仅是底层文件?我的困惑是读取文件是异步的,但解析json是同步的。现在我知道,在读取文件时,可以使用wait来等待loadString返回的将来完成。但是我如何“等待”json解析的完成呢 jsonDecode不接受Future作为它的参数,并且它是同步运行的,所以我不能将它的结果包装成Future(或者我可以吗?)。如果我能找到一个未来的\u string2Item;作为json解

我是新手。我试图在dart中解析一些json,但对读取底层文件的异步性质感到困惑

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

jsonDecode不接受Future作为它的参数,并且它是同步运行的,所以我不能将它的结果包装成Future(或者我可以吗?)。如果我能找到一个未来的\u 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.
class ItemsRepository
{
Map _String2项目;
//不幸的是,这不起作用。但是,我不想返回一个尚未完成json解析的实例
ItemsRepository()异步
{
等待初始化();
}
Future\u loadFile()异步{
return wait-rootBundle.loadString('assets/data/item_int2string.json');
}
Future init()异步
{
var_fileContents=_loadFile();
_string2Item=jsonDecode(等待文件内容);
}
Item getItem(字符串id)
{
返回_string2Item[id];
}
}
//... 在我的代码中的其他地方
ItemRepository ir=ItemRepository();
第(42)项//这会崩溃,因为_string2Item尚未完成解析。
感谢您的帮助。

使用:

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];
}
class ItemsRepository{
Map _String2项目;
Future init()异步{
_string2Item=jsonDecode(
等待rootBundle.loadString('assets/data/item_int2string.json');
}
Item getItem(字符串id)=>\u string2Item[id];
}
您可以删除整个类并用函数替换它:

Future<Map<String, Item>> getItems() async => jsonDecode(
      await rootBundle.loadString('assets/data/item_int2string.json'),
    );   
Future getItems()异步=>jsonDecode(
等待rootBundle.loadString('assets/data/item_int2string.json'),
);   
像这样使用它

  Map<String, Item> items = await getItems();
  print(items['42']);
Map items=wait getItems();
印刷品(项目"42");;

是否有办法避免额外的init调用,并在构造函数中完成所有操作?还有,有没有办法将_string2Item声明为未来的,这样我就可以在其他地方检查是否完成了?构造函数(甚至工厂构造函数)可能不是异步的,所以,没有。因为ItemsRepository类似乎不再有什么作用了,所以可以用一个简单的顶级函数替换它-请参阅更新的答案。Ok。关于我的第二个问题。是否可以将_string2Item声明为在init()完成后完成的未来?这样我就可以有多个侦听器,它们都在等待将来的完成并自动恢复。我考虑的是发布-订阅模式或wait()/notify()的多线程处理。未来不能有多个waiter。颤振替代方案是一个广播流(如在BLoC模式中使用的)或一个
InheritedWidget
,它提供null(或其他伪值),直到该值可用且之后的值可用。