You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter异步函数更新Firestore文档后未同步使用更新数据问题

问题与解决方案

问题描述

我编写了一个Flutter异步函数joinUserToChallenge,逻辑为先更新ChallengesRecord文档将当前用户加入挑战,再基于更新后的文档数据批量更新ff_user_push_notifications集合中的文档用于推送通知。但实际运行时,批量更新操作并未使用更新后的ChallengesRecord数据,而是调用了更新前的旧数据。控制台输出显示文档更新已成功完成,但修改代码后问题依旧。

原代码

Future<void> joinUserToChallenge(ChallengesRecord challenge) async {
 //this updates the ChallengesRecord challenge
 final challengesUpdateData = {
   'users_inchallenge': FieldValue.arrayUnion([currentUserReference])
 };
 await challenge.reference.update(challengesUpdateData).then((value) =>
 print('success'));

 //this then queries the notification documents to be updated then
 //iterates through them to update each one on a batch.commit()
 //however it is not using the updated challenges doc it appears
 final batch = FirebaseFirestore.instance.batch();
 await FirebaseFirestore.instance
    .collection('ff_user_push_notifications')
    .where(filter 1)
    .where(filter 2)
    .get().then((snapshots) => {
    snapshots.docs.forEach((doc) => {
 batch.update(doc.reference, {
    "user_refs" : challenge
    .usersInchallenge.map((u) => u.path).join(',')
     }),
 print(snapshots.docs.length)
  })
 });
 await batch.commit();
}

更新后的尝试代码

Future<void> joinUserToChallenge(ChallengesRecord challenge) async {
  //this updates the ChallengesRecord challenge
  final challengesUpdateData = {
    'users_inchallenge': 
 FieldValue.arrayUnion([currentUserReference])
 };
 await challenge.reference.update(challengesUpdateData).then((value) 
  => print('success'));

 final batch = FirebaseFirestore.instance.batch();
 await FirebaseFirestore.instance
    .collection('ff_user_push_notifications')
    .where(filter 1)
    .where(filter 2)
    .get();

 pushNotificiations.docs.forEach((doc) => {
   batch.update(doc.reference, {
   "user_refs" : challenge
   .usersInchallenge.map((u) => u.path).join(',')
  }),
 });
 await batch.commit()
}

问题原因与解决办法

核心原因

你手中的challenge对象是更新前的本地实例,即便成功更新了Firestore云端的文档,这个本地对象的usersInchallenge属性不会自动同步更新,导致后续批量更新时依然使用旧数据。

解决方法

方法1:手动更新本地对象属性

在成功更新Firestore文档后,直接将当前用户添加到本地challenge对象的usersInchallenge列表中:

Future<void> joinUserToChallenge(ChallengesRecord challenge) async {
  final challengesUpdateData = {
    'users_inchallenge': FieldValue.arrayUnion([currentUserReference])
  };
  await challenge.reference.update(challengesUpdateData);
  print('success');
  
  // 手动更新本地对象的属性
  challenge.usersInchallenge.add(currentUserReference);

  final batch = FirebaseFirestore.instance.batch();
  final snapshots = await FirebaseFirestore.instance
      .collection('ff_user_push_notifications')
      .where(filter1)
      .where(filter2)
      .get();

  snapshots.docs.forEach((doc) {
    batch.update(doc.reference, {
      "user_refs": challenge.usersInchallenge.map((u) => u.path).join(',')
    });
  });
  await batch.commit();
}

方法2:重新从Firestore拉取最新文档

更新完成后,重新获取该挑战文档的最新数据,替换本地的challenge对象:

Future<void> joinUserToChallenge(ChallengesRecord challenge) async {
  final challengesUpdateData = {
    'users_inchallenge': FieldValue.arrayUnion([currentUserReference])
  };
  await challenge.reference.update(challengesUpdateData);
  print('success');
  
  // 重新拉取最新的挑战文档数据
  final updatedDoc = await challenge.reference.get();
  final updatedChallenge = ChallengesRecord.fromSnapshot(updatedDoc);

  final batch = FirebaseFirestore.instance.batch();
  final snapshots = await FirebaseFirestore.instance
      .collection('ff_user_push_notifications')
      .where(filter1)
      .where(filter2)
      .get();

  snapshots.docs.forEach((doc) {
    batch.update(doc.reference, {
      "user_refs": updatedChallenge.usersInchallenge.map((u) => u.path).join(',')
    });
  });
  await batch.commit();
}

额外修复点

更新后的尝试代码中存在未定义变量pushNotificiations的问题,需要将get()的结果赋值给该变量,如上述解决代码中的写法。

内容的提问来源于stack exchange,提问作者Dennis Ashford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:25:19