我正在运行一个非常简单的Firestore事务,该事务将检查文档是否存在,如果不存在则先将其写入。
(用例正在注册用户名-如果尚未注册,则当前用户可以获取它)
以下是相关的Flutter代码的片段:
DocumentReference usernameDocRef =
Firestore.instance.collection(_USERNAMES).document(username);
await Firestore.instance.runTransaction((transaction) async {
var snapshot = await transaction.get(usernameDocRef);
if (!snapshot.exists) {
transaction.set(usernameDocRef, {
_UsernamesKey.userid: _user.id,
});
}
});
此操作失败,但出现异常“事务重试所有重试失败”。
基于Firestore documentation,失败的发生可能有两个原因:
- 事务在写操作之后包含读操作。读取操作必须始终在任何写入操作之前进行。
- 该事务读取了在事务外部修改的文档。在这种情况下,事务将自动再次运行。该交易被重试了有限次。
我认为我不会触发任何一个。有什么建议吗?
答案 0 :(得分:0)
example transaction in the documentation在调用await
时使用update
。也许您在呼叫set
时也需要这样做:
await Firestore.instance.runTransaction((transaction) async {
var snapshot = await transaction.get(usernameDocRef);
if (!snapshot.exists) {
await transaction.set(usernameDocRef, {
_UsernamesKey.userid: _user.id,
});
}
});
答案 1 :(得分:0)
首先,尝试使用原始快照中的引用,而使用原始文档引用中的不。如果这不起作用,请尝试将[设置]更改为[更新],因为我记得与您现在遇到的错误相同。
DocumentReference usernameDocRef =
Firestore.instance.collection(_USERNAMES).document(username);
await Firestore.instance.runTransaction((transaction) async {
var snapshot = await transaction.get(usernameDocRef);
if (!snapshot.exists) {
await transaction.update(snapshot.reference, {
_UsernamesKey.userid: _user.id,
});
}
});
答案 2 :(得分:0)
最近已修复-https://github.com/flutter/plugins/pull/1206。
如果您使用的是master channel,则此修复程序应该已经可用。对于其他渠道(开发,测试版,稳定版)YMMV。
答案 3 :(得分:-1)
我不是Flutter / Dart专家,但我希望您必须从交易中返回某些信息,以便Firestore知道何时完成:
await Firestore.instance.runTransaction((transaction) async {
var snapshot = await transaction.get(usernameDocRef);
if (!snapshot.exists) {
return transaction.set(usernameDocRef, {
_UsernamesKey.userid: _user.id,
});
}
})