我有一个注册客户端的函数。该函数负责创建用户、用户公司以及添加一些关于用户的 meta数据。然而,该函数的脆弱之处在于,如果其中一个请求失败,用户就会被卡住,无法再次注册。有人告诉我,可以使用事务或批处理来解决这个问题。我研究过writeBatch()和批处理,但您似乎需要引用要更新的文档。然而,在我的情况下,我正在创建新文档-我如何将其重构为事务/批处理?到目前为止,我所拥有的是:
const registerUser = async (user: RegisterUserData) => {
try {
const batch = writeBatch(db);
const test = await runTransaction(db, async (transaction) => {
const userDoc = await createUserWithEmailAndPassword(auth, user.email, user.password);
const userId = userDoc.user.uid;
const companyRef = batch.set(doc(db, 'companies'), {
title: user.companyName,
userCount: 1
});
let isAdmin = false;
if (await setUserAsAdmin(userId)) {
isAdmin = true;
}
batch.set(doc(db, 'users'), {
email: user.email,
userId: userId,
firstName: user.firstName,
lastName: user.lastName,
isAdmin: isAdmin,
role: isAdmin ? 'admin' : 'coach',
clientCount: 0,
// companyId: companyRef.id
});
await batch.commit();
});
console.log('test', test)
} catch (e) {
console.log('error', e);
throw new Error('cant register user: ' + e);
}
};
重构之前的原始函数如下所示(并且正在工作):
const registerUser = async (user: RegisterUserData) => {
try {
const createUser = await createUserWithEmailAndPassword(auth, user.email, user.password);
const createdCompany = await createUserCompany({
title: user.companyName,
userCount: 1
});
let isAdmin = false;
const adminSet = await setUserAsAdmin(createUser.user.uid);
if (adminSet) {
isAdmin = true;
}
await createUserMetaData({
email: user.email,
userId: createUser.user.uid,
firstName: user.firstName,
lastName: user.lastName,
isAdmin: isAdmin,
role: isAdmin ? 'admin' : 'coach',
clientCount: 0,
companyId: createdCompany.id
});
return createUser;
} catch (e) {
throw new Error('cant register user' + e);
}
};
1条答案
按热度按时间jm81lzqq1#
不能在Firestore事务中包含从JS SDK的Auth部分对
createUserWithEmailAndPassword()
方法的调用,事实上,可以包含在Firestore事务中的原子操作集只能是Firestore操作(请参阅doc以获得确切的列表)。因此,虽然您可以在批处理写入中包含两个Firestore写入,但不可能在事务中包含用户创建。
如果您希望避免创建用户但不创建Firestore文档的(罕见)情况,一种可能的解决方案是定期检查这种情况,例如使用scheduled Cloud Function来纠正问题。