【问题标题】:Returning value or object from Firebase cloud function is always null从 Firebase 云函数返回值或对象始终为空
【发布时间】:2021-11-24 19:10:31
【问题描述】:

我正在使用下面的代码从 Firebase 返回一个对象,但该值始终为 null。

这是我的 Firebase 云功能:

exports.useVoucher = functions.https.onCall((data, context) => {
    const type = data.type
    const voucher_code = data.voucher_code
    const current_time = data.current_time
    console.log("useVoucher type is ", type + " and voucher_code is ", voucher_code)
    return admin.database().ref().child("vouchers").child(voucher_code).once("value").then((snapshot) => {
        if (snapshot.exists()) {
            console.log("useVoucher snapshot is ", snapshot.val());
            if (snapshot.val()[type] === true) {
                let path = "vouchers/" + voucher_code + "/" + type
                admin.database().ref().update({
                    [[path]]: current_time
                }, error => {
                    if (error) {
                        console.log("useVoucher failed")
                        return {is_valid: false}
                    } else {
                        console.log("useVoucher succeeded")
                        return {is_valid: true}
                    }
                })
            } else {
                console.log("useVoucher voucher found but type not found or not true")
                        return {is_valid: false}
            }
        } else {
            console.log("useVoucher voucher_code is not valid");
                        return {is_valid: false}
        }
    })
})

这就是我所说的客户端(我删除了一些不相关的代码):

async function testVoucher(type) {
    const voucher_code = input_text.value.trim()
    console.log("submitVoucher voucher_code is ", voucher_code + " type is ", type)
    let current_time = Number(new Date())
    console.log("submitVoucher current_time is ", current_time)
    await useVoucher({ type: type, voucher_code: voucher_code, current_time: current_time })
        .then((res) => {
            console.log("submitVoucher res is ", res)
            let data = res.data
            console.log("submitVoucher data is ", data)
        })
        .catch((error) => {
            console.log("submitVoucher error is ", error)
        })
}

无论云函数采用哪条路径,它总是返回“res is null”。这是为什么呢?

【问题讨论】:

  • 请在最后一个 sn-p(和一般情况下)中不要组合 awaitthen。使用其中一种。
  • 您从 Cloud Function 和客户端获得什么日志输出?您可以将这些添加到您的问题中吗?
  • @FrankvanPuffelen 为什么不能合并它们?

标签: javascript firebase google-cloud-functions


【解决方案1】:

您的问题有两个潜在原因:

  1. 你不chain承诺。更准确地说,您不会返回 admin.database().ref().update(...); 返回的 Promise。您应该在此行前面有一个return
  2. 如果更新成功,您实际上不会返回任何内容。事实上,即使在这一行前面添加return,您也只会返回以防出错,而在成功的情况下不会返回任何内容:admin.database().ref().update({...}, error => { **You only return here**})

由于您使用了多个 if 块,因此使用 async/await 会更容易。以下应该可以解决问题(未经测试):

exports.useVoucher = functions.https.onCall(async (data, context) => {   // See async keyword

    try {
        const type = data.type
        const voucher_code = data.voucher_code
        const current_time = data.current_time
        console.log("useVoucher type is ", type + " and voucher_code is ", voucher_code)

        const snapshot = await admin.database().ref().child("vouchers").child(voucher_code).get();
        if (snapshot.exists()) {
            console.log("useVoucher snapshot is ", snapshot.val());
            if (snapshot.val()[type] === true) {
                let path = "vouchers/" + voucher_code + "/" + type
                await admin.database().ref().update({
                    [[path]]: current_time
                });
                return { is_valid: true }
            } else {
                console.log("useVoucher voucher found but type not found or not true")
                return { is_valid: false }
            }
        } else {
            console.log("useVoucher voucher_code is not valid");
            return { is_valid: false }
        }
    } catch (error) {
        console.log(error);
        // Important: Look in the doc how to deal with an error in a Callable Cloud Function.
        //https://firebase.google.com/docs/functions/callable#handle_errors
    }

});

请注意,我们使用get() 方法。 once("value") 是正确的,但使用 get() 更清晰易读(get() 对于客户端 SDK 还具有其他一些优势,请参阅 doc)。

【讨论】:

    【解决方案2】:

    您可以尝试将云函数包装在 promise 中,以便在执行完成时返回解析回调并拒绝。

    exports.useVoucher = functions.https.onCall((data, context) => {
        const type = data.type
        const voucher_code = data.voucher_code
        const current_time = data.current_time
        console.log("useVoucher type is ", type + " and voucher_code is ", voucher_code)
        return new Promise(function (resolve, reject) {
            admin.database().ref().child("vouchers").child(voucher_code).once("value").then((snapshot) => {
                if (snapshot.exists()) {
                    console.log("useVoucher snapshot is ", snapshot.val());
                    if (snapshot.val()[type] === true) {
                        let path = "vouchers/" + voucher_code + "/" + type
                        admin.database().ref().update({
                            [[path]]: current_time
                        }, error => {
                            if (error) {
                                console.log("useVoucher failed")
                                reject({ is_valid: false })
                            } else {
                                console.log("useVoucher succeeded")
                                resolve({ is_valid: true })
                            }
                        })
                    } else {
                        console.log("useVoucher voucher found but type not found or not true")
                        reject({ is_valid: false })
                    }
                } else {
                    console.log("useVoucher voucher_code is not valid");
                    reject({ is_valid: false })
                }
            })
        }
        
    })
    

    【讨论】:

    • 这里不需要返回自定义的Promiseonce() 调用已经返回了一个承诺,所以 OP 应该能够冒泡他们的结果。
    猜你喜欢
    • 2020-01-02
    • 2019-02-27
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 2017-03-15
    相关资源
    最近更新 更多