Flutter web Future .then/.whenComplete
Flutter web Future .then/.whenComplete
请帮助我理解,为什么这段代码不起作用!
我尝试从 Stream (Firestore) 中获取数据,并将这些数据放入列表中。我想等到列表准备好,然后用这个列表做一些事情。但是 .then 或 .whenComplete 在列表准备好之前触发......
这是制作列表的函数,return 它:
Future<List<EventDistance>> getEventsDistanceList(String eventId) async{
Stream<FS.QuerySnapshot> qs = EventDistanceDataRepository().getStreamByEventId(eventId: eventId);
List<EventDistance> dList = [];
EventDistance eventDistance;
qs.forEach((document) {
document.forEach((docs) {
eventDistance = eventDistanceFromJson(docs.data());
dList.add(eventDistance);
print(eventDistance.Name); //(3.) only for testing, to see if docs is not empty
}
);
});
print('return'); //(1.) only for testing, to see when return is fired
return dList;
}
(return 之前也会触发)
我这样使用这段代码:
Future<List<EventDistance>> dList = getEventsDistanceList(filteredList[index].id );
dList.then((value) {
print('value: $value'); //(2.) only for testing,to see if the returned list is empty or not (empty :-( )
doSomething;
});
当我运行时,我首先收到'return'(1.),然后'value: null'(2.)(和一个空列表)然后是列表的元素(姓名 1、姓名 2 ...) (3.)。
我有什么错?如何等待先收到列表?
感谢您的回答!
您需要在异步函数中使用await。我猜
Stream<FS.QuerySnapshot> qs =
EventDistanceDataRepository().getStreamByEventId(eventId: eventId);
应该是
Stream<FS.QuerySnapshot> qs = await
EventDistanceDataRepository().getStreamByEventId(eventId: eventId);
凡是需要很长时间的操作发生的地方都会得到 await 关键字。
Try the code labs to get better with async await
要对异步操作更有信心,请阅读完美的
article by Didier Boelens
让我们检查一下您的代码中发生了什么
您的 getEventsDistanceList() 例程是纯同步的 - 它的所有内容都逐步同步运行
- 同步订阅
qs.forEach
中的流并设置回调侦听器 (document) { ... }
将在每个流项目上触发 somewhere in future
- 同步调用
print('return')
被触发
- 终于
getEventsDistanceList()
returns
- 你听从
getEventsDistanceList()
返回的这个 Future 直到它完成,然后 then()
被调用 print('value: $value')
- 收到第一个流项目并使用 print(eventDistance.Name)
触发回调
第 5 步将对新项目重复,直到流完成或以错误结束(参见 Stream.forEach 实施)
我想你只需要第一个流项目(如果没有,请不要犹豫,在评论中联系我)
如果是这样重写你的代码
EventDistanceDataRepository()
.getStreamByEventId(eventId: eventId)
.first
.then((document) => document.map((docs) => eventDistanceFromJson(docs.data())).toList())
.then((value) { doSomething;});
我更喜欢可读性更好的await
符号
final FS.QuerySnapshot document = await EventDistanceDataRepository()
.getStreamByEventId(eventId: eventId)
.first;
final List<EventDistance> listOfEvents = document.docs.map((e) => eventDistanceFromJson(e.data())).toList();
doSomething with this list
工作正常!最终代码是:
final List<EventDistance> listOfEvents = document.docs.map((e) => eventDistanceFromJson(e.data())).toList();
请帮助我理解,为什么这段代码不起作用! 我尝试从 Stream (Firestore) 中获取数据,并将这些数据放入列表中。我想等到列表准备好,然后用这个列表做一些事情。但是 .then 或 .whenComplete 在列表准备好之前触发...... 这是制作列表的函数,return 它:
Future<List<EventDistance>> getEventsDistanceList(String eventId) async{
Stream<FS.QuerySnapshot> qs = EventDistanceDataRepository().getStreamByEventId(eventId: eventId);
List<EventDistance> dList = [];
EventDistance eventDistance;
qs.forEach((document) {
document.forEach((docs) {
eventDistance = eventDistanceFromJson(docs.data());
dList.add(eventDistance);
print(eventDistance.Name); //(3.) only for testing, to see if docs is not empty
}
);
});
print('return'); //(1.) only for testing, to see when return is fired
return dList;
}
(return 之前也会触发) 我这样使用这段代码:
Future<List<EventDistance>> dList = getEventsDistanceList(filteredList[index].id );
dList.then((value) {
print('value: $value'); //(2.) only for testing,to see if the returned list is empty or not (empty :-( )
doSomething;
});
当我运行时,我首先收到'return'(1.),然后'value: null'(2.)(和一个空列表)然后是列表的元素(姓名 1、姓名 2 ...) (3.)。 我有什么错?如何等待先收到列表? 感谢您的回答!
您需要在异步函数中使用await。我猜
Stream<FS.QuerySnapshot> qs =
EventDistanceDataRepository().getStreamByEventId(eventId: eventId);
应该是
Stream<FS.QuerySnapshot> qs = await
EventDistanceDataRepository().getStreamByEventId(eventId: eventId);
凡是需要很长时间的操作发生的地方都会得到 await 关键字。 Try the code labs to get better with async await
要对异步操作更有信心,请阅读完美的 article by Didier Boelens
让我们检查一下您的代码中发生了什么
您的 getEventsDistanceList() 例程是纯同步的 - 它的所有内容都逐步同步运行
- 同步订阅
qs.forEach
中的流并设置回调侦听器(document) { ... }
将在每个流项目上触发somewhere in future
- 同步调用
print('return')
被触发 - 终于
getEventsDistanceList()
returns - 你听从
getEventsDistanceList()
返回的这个 Future 直到它完成,然后then()
被调用print('value: $value')
- 收到第一个流项目并使用 print(eventDistance.Name) 触发回调
第 5 步将对新项目重复,直到流完成或以错误结束(参见 Stream.forEach 实施)
我想你只需要第一个流项目(如果没有,请不要犹豫,在评论中联系我)
如果是这样重写你的代码
EventDistanceDataRepository()
.getStreamByEventId(eventId: eventId)
.first
.then((document) => document.map((docs) => eventDistanceFromJson(docs.data())).toList())
.then((value) { doSomething;});
我更喜欢可读性更好的await
符号
final FS.QuerySnapshot document = await EventDistanceDataRepository()
.getStreamByEventId(eventId: eventId)
.first;
final List<EventDistance> listOfEvents = document.docs.map((e) => eventDistanceFromJson(e.data())).toList();
doSomething with this list
工作正常!最终代码是:
final List<EventDistance> listOfEvents = document.docs.map((e) => eventDistanceFromJson(e.data())).toList();