如何将事务代码移动到另一个函数中

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