gpt4 book ai didi

promise - Firestore 事务产生控制台错误 : FAILED_PRECONDITION: the stored version does not match the required base version

转载 作者:行者123 更新时间:2023-12-04 16:29:46 27 4
gpt4 key购买 nike

我写了一些代码,允许用户以类似于 Reddit 的方式对食谱进行投票。

每个单独的投票都存储在名为 votes 的 Firestore 集合中,其结构如下:

{username,recipeId,value}(其中值为 -1 或 1)

食谱存储在recipes 集合中,其结构有点像这样:{title,username,ingredients,instructions,score}

每次用户对食谱投票时,我都需要将他们的投票记录在投票集合中,并更新食谱的分数。我想使用事务作为原子操作来执行此操作,因此这两个值永远不会不同步。

以下是我目前的代码。我正在使用 Angular 6,但是我找不到任何展示如何在单个事务中处理多个 gets() 的 Typescript 示例,所以我最终改编了一些我找到的基于 Promise 的 JavaScript 代码。

代码似乎可以工作,但发生了一些令人担忧的事情。当我快速连续单击赞成票/反对票按钮时,偶尔会出现一些控制台错误。这些读取 POST https://firestore.googleapis.com/v1beta1/projects/myprojectname/databases/(default)/documents:commit 400 ()。当我查看来自服务器的实际响应时,我看到了:

{
"error": {
"code": 400,
"message": "the stored version (1534122723779132) does not match the required base version (0)",
"status": "FAILED_PRECONDITION"
}
}

请注意,当我慢慢点击按钮时不会出现错误。

我应该担心这个错误,还是它只是事务重试的正常结果?如 Firestore 文档中所述,“调用事务的函数(事务函数)可能运行超过如果并发编辑影响事务读取的文档,则一次。”

请注意,我已尝试在下面的每个操作周围包装 try/catch block ,并且没有抛出任何错误。为了使代码更易于理解,我在发布之前删除了它们。

非常有兴趣听到任何改进我的代码的建议,无论它们是否与 HTTP 400 错误有关。

async vote(username, recipeId, direction) {

let value;

if ( direction == 'up' ) {
value = 1;
}

if ( direction == 'down' ) {
value = -1;
}

// assemble vote object to be recorded in votes collection
const voteObj: Vote = { username: username, recipeId: recipeId , value: value };

// get references to both vote and recipe documents
const voteDocRef = this.afs.doc(`votes/${username}_${recipeId}`).ref;
const recipeDocRef = this.afs.doc('recipes/' + recipeId).ref;

await this.afs.firestore.runTransaction( async t => {

const voteDoc = await t.get(voteDocRef);
const recipeDoc = await t.get(recipeDocRef);
const currentRecipeScore = await recipeDoc.get('score');

if (!voteDoc.exists) {

// This is a new vote, so add it to the votes collection
// and apply its value to the recipe's score
t.set(voteDocRef, voteObj);
t.update(recipeDocRef, { score: (currentRecipeScore + value) });

} else {

const voteData = voteDoc.data();

if ( voteData.value == value ) {

// existing vote is the same as the button that was pressed, so delete
// the vote document and revert the vote from the recipe's score
t.delete(voteDocRef);
t.update(recipeDocRef, { score: (currentRecipeScore - value) });

} else {

// existing vote is the opposite of the one pressed, so update the
// vote doc, then apply it to the recipe's score by doubling it.
// For example, if the current score is 1 and the user reverses their
// +1 vote by pressing -1, we apply -2 so the score will become -1.
t.set(voteDocRef, voteObj);
t.update(recipeDocRef, { score: (currentRecipeScore + (value*2))});
}

}

return Promise.resolve(true);

});

}

最佳答案

According to Firebase developer Nicolas Garnier ,“您在这里遇到的是事务在 Firestore 中的工作方式:其中一个事务写入失败,因为同时数据已更改,在这种情况下,Firestore 会再次重新运行事务,直到成功。在这种情况下同时编写多个评论,其中一些可能需要在第一次事务后再次运行,因为数据已更改。这是预期的行为,这些错误应更多地视为警告。”

也就是说,这是事务重试的正常结果。

我使用 RxJS throttleTime 来防止用户通过快速连续单击 upvote/downvote 按钮将事务淹没在 Firestore 服务器上,这大大减少了 400 错误的发生。在我的应用程序中,没有正当理由有人需要每秒剪辑数十次赞成/反对票。这不是电子游戏。

关于promise - Firestore 事务产生控制台错误 : FAILED_PRECONDITION: the stored version does not match the required base version,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51814139/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com