我使用以下代码从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为null"为什么?
您的问题有两个潜在原因:
- 你不会把承诺挂在链子上。更确切地说,您不会返回
admin.database().ref().update(...);
返回的Promise。这行前面应该有一个return
- 如果更新成功,您实际上不会返回任何内容。事实上,即使在这一行前面添加
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还有一些其他优势,请参阅文档(。
您可以尝试将云函数包装为promise,以便在执行完成时返回resolve和reject的回调。
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 })
}
})
}
})