我正在尝试使用事务重写firebase函数。我现在遇到的问题是,我是否应该归还一份转写承诺?例如,我想使用一个函数,它有一个transception参数。但是这个函数不应该立即执行交易,而是返回它的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 })
}
查看上一个线程和SDK引用后,事务的set()
、update()
和delete()
操作似乎没有返回promise,但它们只是返回相同的Transaction
实例以用于事务链接:
返回事务:此事务实例。用于链接方法调用。
这与返回Promise<DocumentSnapshot>
的get()
方法不同。我测试了一个分为两个功能的简单事务,没有发现明显的问题:
function fireTransaction(){
return fireDB.runTransaction((tr) => {
const myDoc = fireDB.collection("users").doc("testUser1");
return tr.get(myDoc).then(tDoc => {
setUserAgeTR(tr, tDoc.ref)
})
})
.then(res => console.log("Completed"))
.catch(err => console.log("Failed Transaction: ", err))
}
function setUserAgeTR(tr, docRef){
return tr.update(docRef, {userAge: 9999}) //Requires DocumentReference, can be obtained from 'ref'
}
根据SDK文档,由于您使用的是TypeScript,辅助函数的返回类型应该是Transaction
。