Как получить данные Firestore из документов разных коллекций

avatar
Thaanu
8 августа 2021 в 18:59
39
2
0

Я пытаюсь собрать данные из разных документов из разных коллекций, и выполнение этого в цикле for увеличивает время обработки кода

 for (var i = 0; i < productDataList.length; i++) {
      // Get full data according to shared preferences
      var firestore = FirebaseFirestore.instance;
      DocumentSnapshot ds1 = await firestore
          .collection('products')
          .doc(productDataList[i][4])
          .collection(productDataList[i][4])
          .doc(productDataList[i][0])
          .get();

      // Add product DocumentSnapshot to map
      productFullDetails.add({'productDoc': ds1});
}

Кто-нибудь знает лучший способ сделать это? Спасибо.

Источник
Frank van Puffelen
8 августа 2021 в 19:33
0

Что сделало бы другой метод лучше для вас? Итак: в чем проблема с вашим текущим кодом?

Thaanu
9 августа 2021 в 13:52
0

@FrankvanPuffelen Требуется время для загрузки

Ответы (2)

avatar
Victor Eronmosele
9 августа 2021 в 08:05
1

Вы можете переместить асинхронную операцию из цикла for, создав список фьючерсов асинхронных операций и получив сразу все результаты с помощью Future.wait.

  var firestore = FirebaseFirestore.instance;

  final List<Future<DocumentSnapshot>> documentSnapshotFutureList =
      productDataList
          .map((productData) => firestore
              .collection('products')
              .doc(productDataList[i][4])
              .collection(productDataList[i][4])
              .doc(productDataList[i][0])
              .get())
          .toList();

  final List<DocumentSnapshot> documentSnapshotList = await Future.wait(documentSnapshotFutureList);

  productFullDetails = documentSnapshotList
      .map((DocumentSnapshot documentSnapshot) =>
          {'productDoc': documentSnapshot})
      .toList();

При использовании Future.wait,

обратите внимание на следующее.

Возвращает будущее, которое завершится, как только все предоставленные фьючерсы завершились либо со своими результатами, либо с ошибкой, если какой-либо из предоставленные фьючерсы терпят неудачу.

Возвращенное значение future будет списком всех значений, которые были созданы в том порядке, в котором фьючерсы предоставляются путем итерации фьючерсы

https://api.flutter.dev/flutter/dart-async/Future/wait.html

avatar
Huthaifa Muayyad
8 августа 2021 в 20:29
1

Проблема не вызвана циклом for как таковым, посмотрите, что происходит в цикле for. Если вы делаете асинхронный сетевой запрос и ожидаете его. Если у вас есть список продуктов, состоящий из 100 элементов, вам нужно сделать 100 запросов и дождаться завершения каждого из них. Если бы каждый запрос был 200 миллисекунд [что не медленно], это 20 секунд.

Вероятно, я бы не стал делать это в цикле for и воспользовался бы построителем потока для самостоятельного получения каждого отдельного документа в потоке, что технически равно количеству чтений.

Используйте цикл for для создания пара, псевдокод будет выглядеть так:

Column(
 children:[
  for (var product in productDataList) 
    
   StreamBuilder<DocumentSnapshot>(
   stream: FirebaseFirestore.instance
          .collection('products')
          .doc(product[4])
          .collection(product[4])
          .doc(product[0])
          .snapshots(),
   builder: (context, snapshot){
  if(snapshot.hasData) productFullDetails.add({'productDoc': snapshot.data() as Map<String,dynamic>});
return Text('something');

   }
   
)

 ])

Это позволит получать ваши данные одновременно, не дожидаясь, пока они закончатся друг за другом.