【发布时间】:2022-01-11 04:25:12
【问题描述】:
我正在尝试使用事务重写我的 firebase 函数。我现在遇到的问题是,我应该返回交易承诺吗?例如,我想使用一个具有事务参数的函数。但是这个函数不应该立即执行事务,而是返回它的 Promise。
这是我目前的功能:
export const dbUserDocsOnCreated = functions
.region(constants.region)
.firestore
.document("users/{id}")
.onCreate((snapshot, context) => doOnCreatedUserDocs(db, stripe, snapshot, context));
export async function doOnCreatedUserDocs(
db: FirebaseFirestore.Firestore,
stripe: Stripe,
snapshot: functions.firestore.QueryDocumentSnapshot,
context: functions.EventContext
) {
try {
const transactionPromise = db.runTransaction(async (t) => {
const snapshotData: FirebaseFirestore.DocumentData = (await t.get(snapshot.ref)).data() as FirebaseFirestore.DocumentData
// IF onCreate() has already been called once.
if (!isDataNullOrEmpty(snapshotData.eventID)) {
return Promise.all([null])
}
const createdUserNr: string = await getIdTransactionally(t, db, constants.collectionUsers)
const createdStripeUser: Stripe.Response<Stripe.Customer> = await createStripeUser(stripe, snapshotData, firebaseUserEmail, currentUserNr, snapshot.id, idempotencyKey)
const updateUserNrPromise: Promise<FirebaseFirestore.Transaction> = incrementIdTransactionally(t, db, constants.collectionUsers)
const updateUserDocsPromise: Promise<FirebaseFirestore.Transaction> = updateUserDocsTransactionally(t, snapshot.ref, createdUserNr, idempotencyKey)
return Promise.all([
updateUserDocsPromise,
updateUserNrPromise,
])
})
return Promise.all([
transactionPromise
])
} catch (err) {
// CATCHING
}
}
处理事务的使用函数
export async function incrementIdTransactionally(
transaction: FirebaseFirestore.Transaction,
db: FirebaseFirestore.Firestore,
doc: string
): Promise<FirebaseFirestore.Transaction> {
const incrementor: FirebaseFirestore.FieldValue = FirebaseFirestore.FieldValue.increment(1);
const collectionReference: FirebaseFirestore.DocumentReference<FirebaseFirestore.DocumentData> = db.collection(constants.collectionAutoIds).doc(doc)
return transaction.update(collectionReference, { id: incrementor })
}
async function updateUserDocsTransactionally(
transaction: FirebaseFirestore.Transaction,
ref: FirebaseFirestore.DocumentReference,
generatedUserNr: String,
eventId: string,
): Promise<FirebaseFirestore.Transaction> {
return transaction.set(ref, {
userNr: generatedUserNr,
eventId: eventId,
optionalAddress: FirebaseFirestore.FieldValue.delete()
}, { merge: true })
}
function createStripeUser(
stripe: Stripe,
data: FirebaseFirestore.DocumentData,
eMail: string,
usernr: string,
uid: string,
idempotencKey: string,
): Promise<Stripe.Response<Stripe.Customer>> {
return stripe.customers.create({
name: data.fullName,
email: eMail,
description: "Created by Firebase Cloud-Functions",
metadata: { uuid: uid, userNr: usernr },
preferred_locales: ["de-DE"],
}, { idempotencyKey: idempotencKey })
}
【问题讨论】:
-
您似乎正试图根据您正在运行的主函数内部调用的辅助函数在单个事务中执行多个操作。您是否检查过 this question 如何执行多项操作是否有帮助?如果不是,它与您尝试实施的有什么不同?
-
@ErnestoContrerasPinon 您提供的问题正是我想要的。我的问题唯一不同的是,我如何将事务操作移动到另一个函数中。例如,在您提供的问题中,如何将
t.set(userDoc, { "userId" : userId })移动到另一个函数中。这个函数应该返回一个承诺吗??
标签: javascript firebase google-cloud-firestore transactions google-cloud-functions