首页 > 解决方案 > firebase 函数在完成代码处理之前返回

问题描述

我在firebase触发器下面有这个

exports.on_order_received_deduct_doodle_cash = functions.database.ref("/orders/{id}")
    .onCreate((snapshot, context) => {
      console.log("start of on_order_received_deduct_doodle_cash")   

      const order = snapshot.val();
      const customerObj = order.customer
      const orderObj = order.order

      const paymentType = orderObj._paymentType
      console.log("payment type is::" + paymentType)

      if(paymentType === 'DoodleCash'){
        console.log("payment type is DoodleCash so deduct it from customer account")
        const afterDiscount = orderObj._afterDiscount
        const uid = customerObj._uid

        console.log("Customer uid is::" + uid)
        var db = admin.database();
        const userRef = db.ref('users/')
        userRef.child(uid).once("value").then(
            (resp) => {

                console.log("user value:" + JSON.stringify(resp))
                const userObj = resp.val()
                  let doodleCash = userObj._doodleCash
                  console.log("user current doodle cash is::" + doodleCash)
                  if(doodleCash === undefined)
                     doodleCash = 0

                  if(doodleCash > afterDiscount){
                    const val = doodleCash - afterDiscount

                    console.log("new doodle cash will be:" + val)
                    return userRef.child(uid).update({"_doodleCash" : val})
                  }else{
                        console.error("cannot be a negative value")
                        return null
                    }
            }
        ).catch(
            (err) =>  {
                            console.error("something went wrong:" + err)
                            return null
                     }
            )
      }else{
          return null
      }
})

这是我可以看到方法在 userRef.child(uid).once("value") 完成之前完成的执行之一。为什么?或如何解决?我相信我的代码应该在完成触发器之前阻塞并等待 then 完成。我在这里错过了什么吗?请指教

2:25:44.698 AM
on_order_received_deduct_doodle_cash
something went wrong:TypeError: Cannot read property '_doodleCash' of null

2:25:44.698 AM
on_order_received_deduct_doodle_cash
user value:null

2:25:36.406 AM
on_order_received_deduct_doodle_cash
Function execution took 618 ms, finished with status: 'ok'

2:25:36.198 AM
on_order_received_deduct_doodle_cash
Function returned undefined, expected Promise or value

2:25:35.796 AM
on_order_received_deduct_doodle_cash
Customer uid is::3jwWMscY4mZGATQZg94d7wyRE143

2:25:35.796 AM
on_order_received_deduct_doodle_cash
payment type is DoodleCash so deduct it from customer account

2:25:35.796 AM
on_order_received_deduct_doodle_cash
payment type is::DoodleCash

2:25:35.788 AM
on_order_received_deduct_doodle_cash
Function execution started

标签: node.jsfirebasefirebase-realtime-databasegoogle-cloud-functions

解决方案


正如您将在 Firebase 视频系列 ( https://firebase.google.com/docs/functions/video-series/ ) 中有关“JavaScript Promises”的三个官方 Firebase 视频中看到的,对于由事件触发的云函数,您必须在您的 Cloud Function 中返回一个 Promise(或 Promise 链),以向平台指示所有异步工作已完成。

如果您不这样做,平台可能会停止执行您的云功能,这显然是发生在您身上的事情。

因此,您应该按如下方式调整您的代码:

exports.on_order_received_deduct_doodle_cash = functions.database.ref("/orders/{id}")
    .onCreate((snapshot, context) => {
        console.log("start of on_order_received_deduct_doodle_cash")

        const order = snapshot.val();
        const customerObj = order.customer
        const orderObj = order.order

        const paymentType = orderObj._paymentType
        console.log("payment type is::" + paymentType)

        if (paymentType === 'DoodleCash') {
            console.log("payment type is DoodleCash so deduct it from customer account")
            const afterDiscount = orderObj._afterDiscount
            const uid = customerObj._uid

            console.log("Customer uid is::" + uid)
            var db = admin.database();
            const userRef = db.ref('users/')
            return userRef.child(uid).once("value")  // <- Note the return here
            .then(resp => {

                    console.log("user value:" + JSON.stringify(resp))
                    const userObj = resp.val()
                    let doodleCash = userObj._doodleCash
                    console.log("user current doodle cash is::" + doodleCash)
                    if (doodleCash === undefined) {
                        doodleCash = 0
                    }
                    if (doodleCash > afterDiscount) {
                        const val = doodleCash - afterDiscount

                        console.log("new doodle cash will be:" + val)
                        return userRef.child(uid).update({ "_doodleCash": val })
                    } else {
                        console.error("cannot be a negative value")
                        return null
                    }
            })
            .catch(
                (err) => {
                    console.error("something went wrong:" + err)
                    return null
                }
            )
        } else {
            return null
        }
    })

推荐阅读