我有一个firebase v2函数设置在540秒超时,但是httpsCallableFromURL
捕获一个错误说Firebase Error: deadline-exceeded
在函数完成之前。
下面是我的firebase函数模板:
exports.functionname = functions.https.onCall(
{
timeoutSeconds: 540,
cpu: 2,
},
async (req) => {
const getOutput = async (id: string) => {
return new Promise((resolve, reject) => {
return axios.get('ur'l)
.then((res) => {
resolve(res.data)
})
.catch((e) => {
resolve(false)
})
})
}
let output: any
const recurse = async () => {
return new Promise(async (resolve) => {
// first try getting output
output = await getOutput(id).then((res) => {
return res
})
// check for output
if (output.output) {
return resolve(true)
} else if (output.error) {
return resolve(false)
} else {
setTimeout(() => {
return resolve(recurse())
}, 2000)
}
})
}
return recurse()
.then(async () => {
const imageUrl = output.output[0]
function getBase64(url: string) {
return axios
.get(url, {
responseType: 'arraybuffer',
})
.then((response) =>
Buffer.from(response.data, 'binary').toString('base64'),
)
}
const base64Image = await getBase64(imageUrl)
const data = {
type: 'image',
predictionId,
result: base64Image,
}
return data
}
})
.catch((e) => {
return false
})
},
)
如果我监视功能日志,它最终在540秒内完成,但我的客户端从未收到返回值,因为httpsCallableFromURL
错误。
这个问题涉及到计算每个承诺的执行时间的一些调试,因为你的错误与函数中指定的超时有关,超时是540秒,这意味着你所有的承诺都应该在给定的540秒内解决或拒绝。
所以我建议你在每个promise周围放置一些console.time(“Promise 1”)
和console.timeEnd(“Promise 1”)
,这样我们就可以得到每个promise的预期执行时间,并比较函数的总执行时间,用这些数据你可以修改相应的promise,这需要很多时间。有关此主题的更多信息,请查看此线程
如果以上都不起作用,那么你可以把超时时间增加到1800秒,这意味着在给定的超时时间内30分钟完成所有的执行,但这应该作为最佳实践来避免。
找到了原始答案,它解释了您需要在客户端重写timeout参数
exports. functionname = functions.runWith({ timeoutSeconds: 180 }).https.onCall(async (data, ctx) => {
// Your Function Code that takes more than 120 second to run
});
然后在客户端:
firebase.functions().httpsCallable("testFunction", {timeout: 180000});