首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Fi还原事务:如何编写可以作为事务的发起者和非发起者的函数?

Fi还原事务:如何编写可以作为事务的发起者和非发起者的函数?
EN

Stack Overflow用户
提问于 2020-10-15 10:48:11
回答 1查看 73关注 0票数 0

假设我有一个updateLog()函数,它执行以下操作:

只是一个伪:

代码语言:javascript
运行
复制
const updateLog = (logData) => {
   return db.runTransaction( t => {
      return t.get(logRef)
         .then(log => {
            if (!log.exists) {
               // blah blah blah
            } else {
               // blah blah blah
            }
         }
   }
}

但我还有另一个函数,即可以是事务的发起者,而updateLog()函数只能是事务的部分。

代码语言:javascript
运行
复制
const createDoc = (docData) => {
   return db.runTransaction( t => {
      t.set(docRef, docData);
      // Here, the updateLog() can only be part of the transaction.
      return updateLog(docData, t???)
         .then(result => {
            if (!result) {
               // blah blah blah
            } else {
               // blah blah blah
            }
         }
   }
}

问题:,所以在我的updateLog()中,我是否可以接受transaction作为一个可选参数,同时仍然保留它作为独立事务发起者的能力?因此,如何为updateLog()创建一个可选参数,使runTransaction到(可选地)接受它作为事务的一部分?我之所以要这样做,是因为我希望避免重复runTransaction块中的逻辑,或者编写另一个管理事务可用性的“代理”或“路由器”。任何建议都将不胜感激,谢谢!

代码语言:javascript
运行
复制
const updateLog = (logData, transaction = null) => {
   // How do I pass transaction as t in this context?
   // Possible?
   return db.runTransaction( t => {
      return t.get(logRef)
         .then(log => {
            if (!log.exists) {
               // blah blah blah
            } else {
               // blah blah blah
            }
         }
   }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-24 16:44:49

在等待了一个多星期的答复后,显然我们不可能有条件地await firestore.runTransaction()如下:

代码语言:javascript
运行
复制
const updateLog = async (logData, transaction = null) => {
   if (!transaction) {
      transaction = await firestore.runTransaction();
   };
   // Start manipulating data here.
}

您不能等待事务完成并在 runTransaction之外执行数据操作任务--这是完全违背了事务的目的。

解决方案:预测不可预测的

提供成为事务的独立和部分的灵活性的最佳方法是,在任何runTransaction直接数据操作函数中,不是 to ,而是最外层的调用方,例如Firebase函数:

data-layer.js

代码语言:javascript
运行
复制
   const updateLog = (logData, transaction) => {
      if (!transaction || transaction instanceof admin.firestore.Transaction === false) {
         throw new Error(`Invalid argument: transaction. It must be an instance of Firestore Transaction.`);
      };
      // Assuming logRef has been created here. 
      return transaction.get(logRef)
         .then(log => {
            if (!log.exists) {
               // blah blah blah
            } else {
               // blah blah blah
            }
         }
   }

   const createDoc = (docData, transaction) => {
      if (!transaction || transaction instanceof admin.firestore.Transaction === false) {
         throw new Error(`Invalid argument: transaction. It must be an instance of Firestore Transaction.`);
      };
      // Assuming docRef has been created here. 
      transaction.set(docRef, docData);
      // Here, the updateLog() can be part of the transaction.
      return updateLog(docData, transaction)
         .then(result => {
            if (!result) {
               // blah blah blah
            } else {
               // blah blah blah
            }
         }
   }

[消]火基函数

代码语言:javascript
运行
复制
"use strict";
const admin = require("firebase-admin");

exports.createDoc = functions.https.onCall((data, context) => {
   const firestore = admin.firestore();
   // Transaction will only be initiated as needed
   // by the caller.
   return firestore.runTransaction(transaction => {
      return createDoc(data.docData, transaction)
         .then(result => {
            // Log has also been updated when running createDoc()
            return result;
          }
   }.catch(error => {
       throw new functions.https.HttpsError("failed-precondition", `${error.message}`);
   };
});

exports.updateLog = functions.https.onCall((data, context) => {
   const firestore = admin.firestore();
   // The updateLog() now can also be standalone.
   return firestore.runTransaction(transaction => {
      return updateLog(data.logData, transaction)
         .then(result => {
            // Log has been updated.
            return result;
          }
   }.catch(error => {
       throw new functions.https.HttpsError("failed-precondition", `${error.message}`);
   };
});

结论:

让每个较小的数据服务函数接受transaction参数,并在打包为一个完整的任务时启动runTransaction only ,这是一个很好的实践。这应该是相对安全的,特别是当首先验证所需的transaction参数时,同时能够在使用数据服务时提供更大的灵活性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64369907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档