函数是否有可能在文档更新之前退出/关闭,因此文档不会更新?代码中的更多注解:
exports.enterToWin = functions.https.onCall(async (data) => {
const { user } = data;
try {
return await db.runTransaction(async (t) => {
const ref = db.collection(COLLECTION_NAME);
const snap = await ref.where('available', '==', true).get();
const prize = snap.docs[i];
// See how we're updating the prize here...
t.update(prize.ref, {
winner: user,
available: false
});
// ... but we're not waiting for the transaction to complete before returning?
// Could this cause the update to fail, in theory?
return { uid: doc.id, ...doc.data() };
});
} catch (error) {
return { error: 'Unexpected error: ' + error.message };
}
});
像这样等待会更安全/更好吗?
await t.update(prize.ref, {
winner: user,
available: false
});
return { uid: doc.id, ...doc.data() };
函数在99%的时间里都很好。但是我们在生产中遇到了一些问题。一些用户获得了奖品,但是奖品后来似乎消失了。正在尝试解决实际发生的问题。谢谢
1条答案
按热度按时间ej83mcc01#
JavaScript异步函数必须等待,否则在云函数终止之前,promise完全有可能无法解析。这在Firebase文档Sync, async, and promises中有详细说明:
管理函数的生命周期以确保其正确解析非常重要。通过正确终止函数,您可以避免因函数运行时间过长或无限循环而产生的过多费用。此外,您可以确保运行您的函数的Cloud Functions示例在您的函数成功达到其终止条件或状态之前不会关闭。
使用以下推荐的方法来管理函数的生命周期:
这在Cloud Functions的Node.js运行时文档中有进一步的详细说明:
当处理涉及回调或
Promise
对象的异步任务时,必须显式通知运行时函数已完成这些任务的执行。可以通过几种不同的方式来完成此操作,如下面的示例所示。关键是代码必须等待异步任务或Promise
完成后才返回;否则,函数的异步组件可能会在完成之前终止。在Cloud Functions的提示和技巧文档中:
不启动后台活动
后台活动是在函数终止后发生的任何事情。一旦函数返回或以其他方式发出完成信号,函数调用就会完成,例如通过调用Node.js事件驱动函数中的
callback
参数。在优雅终止后运行的任何代码都无法访问CPU,也不会有任何进展。要直接回答您的问题,您必须使用
await
调用update()
,因为它是一个异步函数。您应该配置IDE和/或linter以检查未等待的异步函数,例如使用require-await:此规则警告没有await表达式的异步函数。
此规则的错误代码示例:
此规则的正确代码示例: