【问题标题】:Get Firebase cloud function snapshot children data获取 Firebase 云函数快照子数据
【发布时间】:2020-08-11 20:26:10
【问题描述】:

花了一整天的时间。我真的在为 Typescript 和 Firebase Cloud Functions 苦苦挣扎。 我想 1) 监视我的数据库的“购买”节点。进行新购买时,我想 2) 汇总所有用户的购买,然后 3) 将其发送到我的 CRM (sendinblue)。

我可以让 #1 完成监控。我想出了#3 如何将信息发送到我的 CRM。这是我遇到麻烦的第二个中间步骤。我不知道如何将.once 方法中的信息数组转换为单个值。我只想得到一个像 8.97 这样的数字发送到我的 CRM(即 1.99 + 2.99 + 3.99,仅供参考)。

我的数据库如下所示:

{
  "1": {
    "price": 1.99,
    "product": "Product A",
    "subscriptionExpiryDate": 1569445492
},
  "2": {
    "price": 2.99,
    "product": "Product B",
    "subscriptionExpiryDate": 1575556926
},
  "3": {
    "price": 3.99,
    "product": "Product C",
    "subscriptionExpiryDate": 1587990802
}

这是我的代码:

exports.purchaseTEST3 =
functions.database.ref('/users/{userID}/purchases').onUpdate((change: any, context: any) => {

  const userRef = change.after.ref

  let totalPurchases = 0

  userRef.once("value")
  .then(function(snapshot: any[]) {
    snapshot.forEach(function(childSnapshot) {

      const key = childSnapshot.key
      const childData = childSnapshot.val()

      totalPurchases = totalPurchases + childData

      console.log('TEST3 info:', key, childData, totalPurchases)
      // ^ gives "TEST3 info: 123 { price: 456 } 0[object Object][object Object]"
    })
  })
})

控制台日志如下所示:

TEST 3 info: 0[object Object][object Object][object Object] 3

所以我知道我正在获取信息。我只是不知道如何解析它(或任何术语)。

我是不是搞错了?我看过HEREHEREHERE 以及其他十几个地方。

【问题讨论】:

    标签: typescript firebase google-cloud-functions


    【解决方案1】:

    我对您的最终目标有点困惑...但我假设您希望从每个子节点访问每个单独的子节点(键、值或两者)。如果是这种情况,我会将每个孩子的 childData 添加到 foreach 循环内的数组中。

    在foreach循环之外,创建一个数组对象,然后在循环中,将childData添加到数组中。

    exports.purchaseTEST3 =
    functions.database.ref('/users/{userID}/purchases').onUpdate(async(change: any, context: any) => {
    try{
      const newArray: Array<string> = [];
      let totalPurchases = 0
    
      const CS = await userRef.once("value"); // this will wait for this function to resolve before continuing. CS will be a snapshot object
      CS.forEach(function(childSnapshot) { // I do not use ForEach very often so this is untested syntax but the jist is there
    
          const key = childSnapshot.key // this will be the master key, in this case 1, 2, or 3
          const price = childSnapshot.child("price").val();
          const product = childSnapshot.child("product").val();
          const ExpireDate = childSnapshot.child("subscriptionExpiryDate").val();
          newArray.push(product); // this will be the only thing accessible outside this forEach loop
    
          totalPurchases = totalPurchases + price // You might have to convert price from a string to a number 
    
          console.log('TEST3 info:', key, product, price, ExpireDate, totalPurchases)
        })
        console.log("product 1: " newArray[0]);
        console.log("product 2: " newArray[1]);
        console.log("product 3: " newArray[2]);
    ...
    }
    catch(err){
            console.log(err);
            return err;
    }
    })
    

    请注意,这是未经测试的,因此可能需要进行一些修改,但一般的思考过程应该会坚持下去。

    一旦循环结束,您可以访问数组中的任何节点,前提是您知道它们被访问的顺序。要解决这个问题,请查看“OrderByChild”。

    我还会考虑在您的云函数中使用 async 和 await,而不是返回任务 (.then(function....))。缺少 Google 的打字稿文档,但如果您想了解更多详细信息,请随时回复。我个人喜欢 Firebase 峰会 https://www.youtube.com/watch?v=tResEeK6P5I&t=1101s 的这个 youtube 视频,该视频在 18 分钟标记之前与 async await 相关。

    祝你好运!

    编辑:

    我想我看到了这个问题,您需要更深入地挖掘您的快照。如您的示例中所写, childData 将是一个包含新键和新值的快照。试试这个:

    const price = childSnapshot.child("price").val();
    const product = childSnapshot.child("product").val();
    const ExpDate = childSnapshot.child("subscriptionExpiryDate").val();
    

    在循环内部。我的其余评论仍然有效,但这应该会让你更深入。 child 的字符串参数需要与您的键完全匹配。我更新了上面的代码示例以反映这一变化。

    【讨论】:

    • 是的,就是这样。这就是我所缺少的。我没有将.val() 添加到对象的末尾以获取对象的值。谢谢!!
    • 是的,我想更多地了解如何使用他们的 Typescript 功能。我已经阅读了我可以在他们的网站上找到的所有文档,但我找不到上述问题的答案。我还看过 Doug Stevenson 的视频。这实际上是我获得大部分代码的地方。如果您对去哪里获得更多示例代码和想法有更多想法,我会全力以赴!
    • @PhontaineJudd Doug S 的视频很棒,这也是我在开始使用 Firebase 时选择 Typescript 的主要原因,但是尽管发布了这些视频,但他们已经忘记了 Typescript。我在答案中引用的 Youtube 剪辑是对 Doug Vids 的一个很好的补充,这就是我的大部分 Firebase 特定打字稿知识的来源。我将在上面的答案中更新代码 sn-p 以使用 ASYNC AWAIT,这使代码更易于阅读和理解。如果你打算做很多 FB Typescript,我强烈建议你尽早掌握异步
    • 更新了上面的代码...注意 onUpdate 之后的 async 关键字。我还添加了一个 try catch 块。说了这么多,从技术上讲,您不必再次访问数据库,您在调用 onUpdate 时传递的 snapshot.after 对象中拥有所需的一切(在这种情况下,您将其称为 change.after)。您可以改为使用以下命令获取该数据:change.after.child('1').child('price').val(); 在大多数情况下,像这样堆叠子调用应该可以工作
    • 我来自 Swift 背景,所以所有这些 Typescript 对我来说都是一门外语。感谢您提供的链接和信息。我想我只需要潜入并开始学习async await。 [叹气]
    猜你喜欢
    • 2020-08-07
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2018-07-10
    相关资源
    最近更新 更多