以异步方式使用 .map()、.where() 等迭代助手?
Posted
技术标签:
【中文标题】以异步方式使用 .map()、.where() 等迭代助手?【英文标题】:Use iteration helpers like .map(), .where(), etc in an async manner? 【发布时间】:2019-07-19 00:42:20 【问题描述】:简短: toList()
在 makeMaker
之前执行,导致 markers
具有 null
对象。
Long:在 Firestore 中,我有 table
和 game
集合,在 table
内部,有一个 game
字段(type=reference)。使用StreamBuilder
,我可以访问table
s。我遍历table
s 并尝试使用get
用真实数据填充他们的game
字段,如下所示;
if (snapshot.hasData)
tabledocs = snapshot.data.documents;
markers = tabledocs
.map((tabledoc)
DocumentReference gameref = tabledoc.data['game'];
//game field is a reference type field which points to another collection
gameref.get().then((gdoc)
tabledoc.data['game'] = gdoc;
Marker marker = makeMarker(tabledoc); //<--------Executes later
return marker;
);
).toList(); //<--------Executes first
因为gameref.get().then()
需要时间,所以底部的toList()
在每个标记生成并添加到markers
之前执行。
如果有 3 个标记从 Firestore 返回,我们的 markers
是一个由 3 个 null
marker
s 组成的数组。我认为makeMarker(..)
很可能还没有执行。
有没有办法让map
方法等待get
s 完成,然后用非空值初始化markers
数组?或者你能告诉我另一种方法来完成我想要的。
【问题讨论】:
【参考方案1】:你可以使用
await for(var tabledoc of tabledocs)
或者如果不需要按顺序执行项目(结果将按照原始项目的顺序)
var markers = await Future.wait(tabledocs
.map((tabledoc)
DocumentReference gameref = tabledoc.data['game'];
//game field is a reference type field which points to another collection
var gdoc = await gameref.get();
tabledoc.data['game'] = gdoc;
Marker marker = makeMarker(tabledoc);
return marker;
);
【讨论】:
非常酷。我从未见过await for
,所以我会选择Future.wait()
。但是await for
读起来更清晰,因为我现在看到了它。
你不应该在StreamBuilder
中做这样的事情。最好在initState
或didChangeDependencies
中执行此操作,并使用setState(...)
将结果存储在字段中并启动重建。您可能需要将代码移动到您从 initState
调用的方法中才能使用 async
。
从 Firestore 获取它们可能是不使用 StreamBuilder
的一个很好的理由,否则每次重建小部件时都会获取它们。
好的,我会根据您的指导尽可能多地更改代码。很快就会回信。一如既往的感谢
@GünterZöchbauer 感谢您带领我走向正确的道路以上是关于以异步方式使用 .map()、.where() 等迭代助手?的主要内容,如果未能解决你的问题,请参考以下文章