请注意,以下方案使用Cloud Firestore 。
在我的云计算功能FULLTEXT
中,我有一个功能index.js
,它将新创建的用户添加到createUserAccount
集合,并为其电子邮件,照片,收藏夹设置字段(此是应用程序中的一个功能,不需要详细说明),以及用户的其他一些不同的字段。成功完成以下代码片段后会触发该功能:
users
如您所见,当任务成功完成时,会调用一些方法:// The following method has been simplified to focus on the problem statement
public void createAccountWithEmailAndPassword(String username, String displayName,
String someOtherImportantThing) {
mFirebaseAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(getActivity(), task -> {
if (task.isSuccessful()) {
Log.d(TAG, "createUserWithEmail:Success");
onSuccess.updateAccount(displayName, username);
updateUsernameProperty(username);
onBackPressed();
} else {
if (task.getException() != null) {
if (task.getException()
.getMessage()
.contains(EMAIL_EXISTS_ERROR)) {
// Handle Email Exists Error
}
}
Log.w(TAG, "createUserWithEmail:failure",
task.getException());
}
});
}
和updateUsernameProperty(String username)
updateAccount(String displayName, username)
获取用户选择的displayName,并将其作为字段添加到用户帐户。 这不会对用户集合进行更改 - 仅对经过身份验证的帐户进行更改。
updateAccount(String displayName)
会将用户选择为userName,将此属性设置为用户文档中的字段。以下是代码示例,因为它可能有助于理解我的问题:
updateUsernameProperty(String username)
(该集合的典型路径为" users / {userId} / username" )
问题:尝试更新用户文档中的用户名字段时,云功能private void updateUsernameProperty(String username) {
DocumentReference docRef = mFirestore
.collection(TABLE_USERS)
.document(mFirebaseAuth.getUid());
docRef.update(USERNAME_KEY, username)
.addOnSuccessListener(aVoid -> Log.d(TAG, "Username DocumentSnapshot Successful"))
.addOnFailureListener(e -> Log.e(TAG, "Error Updating Document: user/uid/username", e));
}
尚未完成创建/添加新用户文档到数据库(即异步)问题)。
我考虑过使用rxJava2来帮助解决这个问题,但我似乎无法理解如何做到这一点。任何帮助是极大的赞赏。
如果您需要澄清某些内容,我会尽力提供所需信息。
答案 0 :(得分:3)
如果我理解正确,您有以下流程:
createUserWithEmailAndPassword
但是第2步和第3步是竞争条件,因为在客户端上发布更新时可能无法执行云功能。
问题是update()
调用取决于现有文档。如果您在客户端代码和云功能中使用set()
选项并使用merge
选项,则可以避免出现这种情况。
云功能
function createUserDoc(userId, data) {
var userRef = db.collection('users').doc(userId);
// Set the user document, creating it if it does not exist
// and merging with existing data if it does
return userRef.set(data, { merge: true });
}
Android代码
public void updateUsername(userId, username) {
Map<String, Object> data = new HashMap<>();
data.put("username", username);
db.collection("users").document(userId)
.set(data, SetOptions.merge());
}