如何将事务代码移动到另一个函数中
How to move transaction code inside another function
我正在尝试使用事务重写我的 firebase 函数。我现在遇到的问题是,我应该 return 交易承诺吗?例如,我想使用一个具有交易参数的函数。但是这个函数不应该立即执行交易,而是 return 它的 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 })
}
在审查 previous thread and the SDK reference, it looks like the set()
, update()
, and delete()
operations 交易后,不 return 承诺,但它们只是 return 用于交易链中的相同 Transaction
实例:
Returns Transaction: This Transaction instance. Used for chaining method calls.
这与 get()
method 不同,return 和 Promise<DocumentSnapshot>
。我测试了一个分成两个函数的简单事务,没有发现明显的问题:
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'
}
由于您使用的是 TypeScript,根据 SDK 文档,您的辅助函数的 return 类型应该是 Transaction
。
我正在尝试使用事务重写我的 firebase 函数。我现在遇到的问题是,我应该 return 交易承诺吗?例如,我想使用一个具有交易参数的函数。但是这个函数不应该立即执行交易,而是 return 它的 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 })
}
在审查 previous thread and the SDK reference, it looks like the set()
, update()
, and delete()
operations 交易后,不 return 承诺,但它们只是 return 用于交易链中的相同 Transaction
实例:
Returns Transaction: This Transaction instance. Used for chaining method calls.
这与 get()
method 不同,return 和 Promise<DocumentSnapshot>
。我测试了一个分成两个函数的简单事务,没有发现明显的问题:
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'
}
由于您使用的是 TypeScript,根据 SDK 文档,您的辅助函数的 return 类型应该是 Transaction
。