如何将对象列表上传到Firestore

时间:2020-04-17 11:28:18

标签: firebase flutter dart google-cloud-firestore

我正在用FireStore开发Flutter应用。

我已经声明了一个变量'total'和对象列表,这些对象将填充来自称为'cart'的集合中的一些数据,然后将这些数据上传到名为'orders'的集合中

此代码从“购物车”集合中获取数据:


void submitOrder() async {

    List<CartItem> products =[];
    double total =0;
    CartItem temp= CartItem(customerId:'' ,itemId:'' ,id: '', title: '', quantity:0, price: 0);

    DatabaseService().cartCollection.getDocuments().then(

       (snapshot) => snapshot.documents.forEach((doc) {

          temp = CartItem(
            customerId: user.uid, 
            itemId: doc.data['itemId'].toString(),
            id: doc.documentID.toString(), 
            title: doc.data['itemName'].toString(),
            quantity: int.tryParse(doc.data['quantity'].toString()) , 
            price: double.tryParse( doc.data['price'].toString()));

            total += temp.quantity*temp.price;
            print(total);  /// This print shows accurate total
            products.add(temp);
            }
          ),
        );
          // Send data to setOrderData in db class to set new doc in order collection                            
          DatabaseService().setOrderData(products, total, user.uid, branchId, 'open');

}

数据库类中的setOrderData方法:

  // Add Order
Future setOrderData(List<CartItem> cartProducts, double total, String customerId, String branchId, String status ) async { 
    final timestamp = DateTime.now();
    return await orderCollection.document(uid).setData(
      {
        'customerId': customerId,
        'branchId': branchId,
        'status': status ,
        'amount': total.toString(), //
        'dateTime': timestamp.toIso8601String(),
        'products': cartProducts.map((cp) => {
          'id': cp.id,
          'title': cp.title,
          'quantity': cp.quantity,
          'price': cp.price,
          }).toList(),
      });
  }

FireStore中的数据显示乘积和总数为空吗?

链接到图像:

Data in Firestore

如果有人可以帮助我,我将不胜感激。

2 个答案:

答案 0 :(得分:0)

高度建议在您的代码上使用一种代码格式化程序,因为这使人们更有可能发现您遇到的问题。重新格式化您共享的第一个代码块时,它变为:

void submitOrder() async {
  List<CartItem> products = [];
  double total = 0;
  CartItem temp = CartItem(
      customerId: '', itemId: '', id: '', title: '', quantity: 0, price: 0);

  DatabaseService().cartCollection.getDocuments().then(
        (snapshot) => snapshot.documents.forEach((doc) {
          temp = CartItem(
              customerId: user.uid,
              itemId: doc.data['itemId'].toString(),
              id: doc.documentID.toString(),
              title: doc.data['itemName'].toString(),
              quantity: int.tryParse(doc.data['quantity'].toString()),
              price: double.tryParse(doc.data['price'].toString()));

          total += temp.quantity * temp.price;
          print(total);

          /// This print shows accurate total
          products.add(temp);
        }),
      );
  // Send data to setOrderData in db class to set new doc in order collection
  DatabaseService().setOrderData(products, total, user.uid, branchId, 'open');
}

以这种格式,我立即可以清楚地知道,您在setOrderData调用中的任何一个发生之前都在呼叫products.add(temp)

这是因为数据是从Firestore异步加载的。由于这可能需要一些时间,因此您的主要代码(包括return)将继续,因此不会阻止UI。然后,当数据可用时,将调用您的then回调。

这意味着需要Firestore中数据的任何代码都必须位于then回调中。因此,在您的情况下,解决方案可能就像将调用setOrderData移到then内部一样简单:

void submitOrder() async {
  List<CartItem> products = [];
  double total = 0;
  CartItem temp = CartItem(
      customerId: '', itemId: '', id: '', title: '', quantity: 0, price: 0);

  DatabaseService().cartCollection.getDocuments().then(
        (snapshot) => snapshot.documents.forEach((doc) {
          temp = CartItem(
              customerId: user.uid,
              itemId: doc.data['itemId'].toString(),
              id: doc.documentID.toString(),
              title: doc.data['itemName'].toString(),
              quantity: int.tryParse(doc.data['quantity'].toString()),
              price: double.tryParse(doc.data['price'].toString()));

          total += temp.quantity * temp.price;
          print(total);

          /// This print shows accurate total
          products.add(temp);
        }),
        // Send data to setOrderData in db class to set new doc in order collection
        DatabaseService().setOrderData(products, total, user.uid, branchId, 'open');
    );
}

因此,需要摆脱的事情:

  1. 始终格式化代码,因为它使您和其他人更容易理解流程并发现问题。
  2. 数据是从Firestore(和大多数云API)异步加载的,您只能在then()回调中使用数据,也可以使用await

答案 1 :(得分:0)

解决此类错误的最佳实践是对每个函数使用try,然后将catchawait一起使用,例如下面的代码

void submitOrder() async {
  List<CartItem> products = [];
  double total = 0;
  CartItem temp = CartItem(
      customerId: '', itemId: '', id: '', title: '', quantity: 0, price: 0);
  try {
    await DatabaseService().cartCollection.getDocuments().then(
          (snapshot) => snapshot.documents.forEach((doc) {
            temp = CartItem(
                customerId: user.uid,
                itemId: doc.data['itemId'].toString(),
                id: doc.documentID.toString(),
                title: doc.data['itemName'].toString(),
                quantity: int.tryParse(doc.data['quantity'].toString()),
                price: double.tryParse(doc.data['price'].toString()));

            total += temp.quantity * temp.price;
            print(total);

            /// This print shows accurate total
            products.add(temp);
          }),
        );
    // Send data to setOrderData in db class to set new doc in order collection
    await DatabaseService()
        .setOrderData(products, total, user.uid, branchId, 'open');
  } catch (error) {
    print(error);
  }
}