Firestore:如何更新电子邮件并将其作为单个批处理操作存储在Firestore集合中



我正在编写react本机项目,用户可以使用他们的usernamepassword登录。由于firebase身份验证不具有使用usernamepassword登录的功能,所以我做了一些技巧。注册时,我将用户的email与其他有用的用户信息一起存储在我的Users集合中。因此,当用户尝试使用username和密码登录时,我会转到我的Users集合,查找相应的username,并获取相应的email地址。因此,我变相地使用了火库方法.signInWithEmailAndPassword(email, password)。虽然不理想,但它确实起到了作用。

然而,问题是当用户想要将他/她的电子邮件地址更新为新地址时。然后,我当然想更新我的用户集合中的email值,这样我就可以执行正确的登录

const onChangeEmail = async () => {
await firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(async function (userCredential) {
await userCredential.user.updateEmail(newEmail).then(async () => {
await updateEmailInFirestore(newEmail);
});
})
.catch((error) => {
console.log("Error while updating email: ", error);
});
};

其中updateEmailInFirestore执行以下操作:

export const updateEmailInFirestore = async (newEmail) => {
if (!newEmail) {
return;
}
await firebase
.firestore()
.collection("Users")
.doc(firebase.auth().currentUser.uid)
.update({ email: newEmail })
.then(() => console.log("email was updated in user collection: ", newEmail))
.catch((error) => console.log("error while updating email: ", error));
};

上面的代码运行良好,能够完成任务。然而,我遇到的问题是以下场景:如果userCredential.user.updateEmail成功执行,但updateEmailInFirestore失败或抛出异常,该怎么办?然后,我数据库中的值将与用户更新的电子邮件地址不一致,我的登录将失败。

有没有一种方法可以将userCredential.user.updateEmailupdateEmailInFirestore作为批处理操作来执行,从而使两者都成功或都失败?我以前写过批处理操作,但它们是按照const batch = firebase.firestore().batch();的思路进行的,我的第一个操作与firestore无关,而是与firebase身份验证有关?

在确保这两个承诺都得到解决方面,你无能为力。Firebase Auth和Firestore是两种不同的产品,因此没有像批处理写入这样的概念。您可以使用Promise.all()并要求用户在任何一个承诺失败的情况下重试,如下所示。

const updateUserEmail = async () => {
try {
await Promise.all([
user.updateEmail(newEmail),
userDoc.update({
email: newEmail
})
])
} catch (e) {
console.log("Updating email failed")
// prompt user to retry
}
}

一个更好且广泛使用的解决方案是创建一个格式为username@noreply.yourapp.com的电子邮件,并将其与createUserWithEmailAndPassword()一起使用。当用户更新他们的用户名时(如果你想允许该功能(,那么你只需要将电子邮件更新为newUsername@noreply.yourapp.com。如果使用此方法,则不需要Firestore来处理电子邮件。

请注意,由于这些电子邮件不存在,您将无法使用验证电子邮件等功能。

最新更新