Flutter 为什么我的异步函数返回未来<;int>;每个人都在等待?

Flutter 为什么我的异步函数返回未来<;int>;每个人都在等待?,flutter,dart,google-cloud-firestore,Flutter,Dart,Google Cloud Firestore,我使用此函数的目标是返回一个整数,表示用户完成的所有习惯。我的数据库结构是一个习惯的集合,每个习惯都有一个子集合,其中包含它的历史。下面的函数使用一个习惯列表,并使用习惯的ID获取该习惯的历史流。我的问题是,当我试图循环浏览每个习惯的历史时,它会在等待时暂停。如果您有任何建议,我将不胜感激,我仍在努力完全理解流/异步函数 Future<int> getCompleteHabits(User user, List<Habit> habits) async { int c

我使用此函数的目标是返回一个整数,表示用户完成的所有习惯。我的数据库结构是一个习惯的集合,每个习惯都有一个子集合,其中包含它的历史。下面的函数使用一个习惯列表,并使用习惯的ID获取该习惯的历史流。我的问题是,当我试图循环浏览每个习惯的历史时,它会在
等待
时暂停。如果您有任何建议,我将不胜感激,我仍在努力完全理解流/异步函数

Future<int> getCompleteHabits(User user, List<Habit> habits) async {
  int completed = 0;
  if(habits.isNotEmpty) {
    for(Habit habit in habits) {
      Stream<List<HabitHistory>> streamHistory = db.streamHabitHistory(user, habit.id);
      await for(var h in streamHistory){
        print(habit.title);
        print(h);
      }
      print("test");
    }
  }
  return completed;
}
Future getCompleteHabits(用户、列表习惯)异步{
int completed=0;
if(habits.isNotEmpty){
为了(习惯中的习惯){
streamHistory=db.streamHabitHistory(用户,习惯.id);
等待(streamHistory中的var h){
印刷品(习惯、标题);
印刷品(h);
}
打印(“测试”);
}
}
返回已完成;
}
但是,此函数将添加到变量completed,因为我无法访问我尚未访问的所有历史记录

此函数将以下内容打印到控制台,但不会到达
打印(“测试”)

颤栗:晚上11:30上床睡觉

弗拉特:[惯习的例子,'惯习的例子,'惯习的例子,'惯习的例子,'惯习的例子,'惯习的例子']

从:

当流中没有更多的事件时,流就完成了,并且接收事件的代码被通知这一点,就像它被通知新事件到达一样。当使用wait for循环读取事件时,流结束时循环停止

循环挂起的原因是流尚未关闭。它将继续挂起,直到流关闭或在循环中执行
break
return
语句为止。

来自:

当流中没有更多的事件时,流就完成了,并且接收事件的代码被通知这一点,就像它被通知新事件到达一样。当使用wait for循环读取事件时,流结束时循环停止


循环挂起的原因是流尚未关闭。它将继续挂起,直到流关闭,或者直到您在循环中执行
break
return
语句。

正如Abion47所述,流尚未关闭,因此等待永远不会完成。它正在等待新的事件

知道了这一点,我可以使用
wait streamHabitHistory(user,habity.id)。首先
获取列表(因此它不等待事件)。代码如下

Future<int> getCompleteHabits(User user, List<Habit> habits) async {
  int completed = 0;
  if(habits.isNotEmpty) {
    for(Habit habit in habits) {
      List<HabitHistory> history = await db.streamHabitHistory(user, habit.id).first;
      for (HabitHistory h in history) {
        completed = completed + h.completed.length;
      }

    }
  }
  return completed;
}
Future getCompleteHabits(用户、列表习惯)异步{
int completed=0;
if(habits.isNotEmpty){
为了(习惯中的习惯){
List history=await db.streamHabitHistory(user,habity.id);
对于(历史上的习惯性h){
已完成=已完成+h.已完成长度;
}
}
}
返回已完成;
}

正如Abion47所述,流尚未关闭,因此等待永远不会完成。它正在等待新的事件

知道了这一点,我可以使用
wait streamHabitHistory(user,habity.id)。首先
获取列表(因此它不等待事件)。代码如下

Future<int> getCompleteHabits(User user, List<Habit> habits) async {
  int completed = 0;
  if(habits.isNotEmpty) {
    for(Habit habit in habits) {
      List<HabitHistory> history = await db.streamHabitHistory(user, habit.id).first;
      for (HabitHistory h in history) {
        completed = completed + h.completed.length;
      }

    }
  }
  return completed;
}
Future getCompleteHabits(用户、列表习惯)异步{
int completed=0;
if(habits.isNotEmpty){
为了(习惯中的习惯){
List history=await db.streamHabitHistory(user,habity.id);
对于(历史上的习惯性h){
已完成=已完成+h.已完成长度;
}
}
}
返回已完成;
}

Wow ok这很有道理,当你说close时,这与dispose相同吗?如果它被处理,它会知道流已经完成了吗?我刚才也想出了一个解决方法,所以我也要把它作为一个答案。看看我的答案,让我知道你的想法。@AnthonySette你不能用典型的方式“关闭”一条流。流关闭的方式是当其控制器触发“完成”事件时。从这一点来看,firestore包从不费心这么做,而是让流在其侦听器取消订阅后被垃圾收集。这是有一定意义的,因为firestore包中的流设计用于在连接服务以接收更改时获取实时更新。好的,这是有意义的,这是真的,因为当对用户数据库的特定部分进行更改时,应用程序中监听相应流的部分会被更新。非常感谢你!哇,好吧,这很有道理,当你说“关闭”时,这和“处置”一样吗?如果它被处理,它会知道流已经完成了吗?我刚才也想出了一个解决方法,所以我也要把它作为一个答案。看看我的答案,让我知道你的想法。@AnthonySette你不能用典型的方式“关闭”一条流。流关闭的方式是当其控制器触发“完成”事件时。从这一点来看,firestore包从不费心这么做,而是让流在其侦听器取消订阅后被垃圾收集。这是有一定意义的,因为firestore包中的流设计用于在连接服务以接收更改时获取实时更新。好的,这是有意义的,这是真的,因为当对用户数据库的特定部分进行更改时,应用程序中监听相应流的部分会被更新。非常感谢你<流上的code>first
返回
Future
。由于您已经使用了
async
方法,因此可以删除
then
;只需先等待
即可获得列表。(我不建议将
then
await
混合使用,因为这会使fol对代码产生混淆。)