for循环应该等待未来

for-loop should wait for future

我有一个用户 ID 列表,我想从数据库中为每个用户获取一个值并将其写入一个新列表。但是 for 循环不等待未来并抛出错误“未处理的异常:RangeError(索引):无效值:有效值范围为空:0”

List userIDs = ["gsdgsgsgda32", "gwerszhgda7h", "fsdgz675ehds"];
  Future <dynamic> getList() async {
    List items=[];
    for (var i = 0; i < userIDs.length; i++) {
      items[i] = await getUserItems(userIDs[i]);
    }
    return items;
  }

  Future <String?> getUserItems(String? _userID) async {
    String? userItem=" ";
    final FirebaseApp testApp = Firebase.app();
    final FirebaseDatabase database = FirebaseDatabase.instanceFor(app: testApp);
    database.ref().child('users').child(_userID!).once().then((pdata) {
      userItem = pdata.snapshot.child('item').value as String?;
      });
    return userItem;
  }

这不是未来的问题。列表项为空,因此当您调用 items[0] = 3; 时没有 items[0],您会得到 RangeError。将元素添加到列表的正确方法是调用 items.add(3)

因此您的代码应如下所示:

List userIDs = ["gsdgsgsgda32", "gwerszhgda7h", "fsdgz675ehds"];
  Future <dynamic> getList() async {
    List items=[];
    for (var i = 0; i < userIDs.length; i++) {
      final item = await getUserItems(userIDs[i]);
      items.add(item); 
    }
    return items;
  }

  Future <String?> getUserItems(String? _userID) async {
    String? userItem=" ";
    final FirebaseApp testApp = Firebase.app();
    final FirebaseDatabase database = FirebaseDatabase.instanceFor(app: testApp);
    database.ref().child('users').child(_userID!).once().then((pdata) {
      userItem = pdata.snapshot.child('item').value as String?;
      });
    return userItem;
  }

试试这样用

 Future <dynamic> getList() async {
        List items=[];
        userIDs.forEach((item) async {
          items.add(await getUserItems(item));
        });
        return items;
      }

通过使用 .then,您告诉 dart 继续 运行 并在 Future 完成时返回。 相反,您应该在 getUserItems.

中使用 await

您需要 fiddle 绕一圈,但这里有一个开始的建议:

Future <String?> getUserItems(String? _userID) async {
    String? userItem=" ";
    final FirebaseApp testApp = Firebase.app();
    final FirebaseDatabase database = FirebaseDatabase.instanceFor(app: testApp);
    userItem = (await database.ref().child('users').child(_userID!).once()).snapshot.child('item').value as String?
    return userItem;
  }

还对 userItem 使用 String? 并将其设置为 " " 有点反模式。既然你允许它可以为 null,我建议将它作为 null 来编写你的逻辑。