如何防止事务写入冲突和异步runTransaction?

时间:2019-04-17 20:01:09

标签: javascript transactions async-await google-cloud-firestore

因此,我目前正在运行一些脚本来重置我们一个应用程序中的用户余额。我正在使用Firestore来获取所有任务,然后根据每个用户的需求来计算余额。听起来很简单吧?应该是,不是。问题在于,由于对同一文档的写冲突,事务正在中止。之所以发生这种情况,是因为所有任务都同时传递给了事务。

我尝试使用forEach方法,这导致他们中止,因为它每次都尝试更新同一用户记录。 而且我尝试了(让任务任务执行),这给了我一个错误“无法完成任务”。

async function updatestuff(){
  console.log("start");
  const tasksRef = db.collection('tasks');
  try {
          const allTasksSnapShot = await tasksRef.get();
          allTasksSnapShot.forEach(async(doc) => {
            //Run transaction for calculations for each task here
            const tskUser = doc.data().taskUser;
            const tuser = db.collection('backupusers').doc(tskUser);
                if(doc.data().taskStatus == 'Not Completed'){
                  console.log('NOT');}
                if(doc.data().taskStatus != 'Not Completed'){
                  console.log('Run transaction here and wait for it to finish?');
                  await db.runTransaction(async t => {
                  const userSnapShot =  await t.get(tuser);
                          if (!userSnapShot) {return console.log('not a thing')}
                          //get new balance calculated
                          const newBalance = userSnapShot.actualbalance + doc.data().taskBalanceAdj;
                          await t.update(tuser, {actualbalance: newBalance});
                  })
            }});
          console.log("end")
  }
  catch (err) {
    console.log('Error getting documents', err);
  }
}

当前,文档写入之间的冲突导致事务中途终止。

如果有人可以帮助我以异步方式将每个任务传递给事务,等待事务完成,然后再传递下一个任务,我将非常感激。 或将获得相同结果的另一种方法。...

预先感谢您好心善良的灵魂!

1 个答案:

答案 0 :(得分:0)

您的updatestuff函数启动了许多异步工作,但是并没有返回一个承诺,当它们全部完成后,它就可以解决。您将在主触发器函数中使用该承诺,以使Cloud Functions知道所有工作已完成,并且可以安全地清理所有内容。如果您不这样做,那么您的功能可能会在工作完成之前被关闭。

请记住,对forEach使用async / await并不是一个好主意。在继续进行下一项之前,forEach函数不会等待异步工作完成。随着大量交易的进行,它将结束,而无法知道何时完成所有交易。相反,您可能希望使用async / await,而是将所有交易承诺推送到一个数组中,然后在该数组上使用Promise.all()创建一个新的承诺,当所有工作完成。从函数中返回它,然后在主触发器函数中使用它。