理论上,功能退出会太早吗?



是否有可能在文档更新之前退出/关闭该函数,从而使文档不更新?代码中的更多注释:

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%的情况下工作良好。但是我们在生产中遇到了一些问题。一些用户获得了奖品,但奖品后来似乎消失了。试图解决实际发生的问题。由于

JavaScript异步函数必须等待,否则完全有可能在云函数终止之前承诺不会解决。这在Firebase文档Sync, async, and promises中有详细说明:

管理函数的生命周期以确保其正确解析是很重要的。通过正确终止函数,可以避免运行时间过长或无限循环的函数产生过多的费用。此外,您可以确保运行您的函数的Cloud Functions实例在您的函数成功达到其终止条件或状态之前不会关闭。

使用以下推荐的方法来管理功能的生命周期:

  • 通过返回JavaScript承诺来解析执行异步处理的函数(也称为"后台函数")。

这在The Node.js Runtime documentation for Cloud Functions中有进一步的详细说明:

当处理涉及回调或Promise对象的异步任务时,你必须显式地通知运行时你的函数已经完成执行这些任务。您可以通过几种不同的方式实现这一点,如下面的示例所示。关键是你的代码必须等待异步任务或Promise在返回之前完成;否则,函数的异步组件可能会在完成之前被终止。

在Tips &云函数的技巧文档:

不要启动后台活动

后台活动是指函数终止后发生的任何事情。函数调用一旦函数返回或发出完成信号就结束,例如在Node.js事件驱动函数中调用callback参数。在优雅终止后运行的任何代码都不能访问CPU,也不会取得任何进展。

直接回答你的问题,你必须await调用update(),因为它是一个异步函数。你应该配置你的IDE和/或linter来检查未等待的异步函数,例如,使用require-await:

该规则警告没有await表达式的异步函数。

规则的错误代码示例:

/*eslint require-await: "error"*/
async function foo() {
doSomething();
}
bar(async () => {
doSomething();
});

正确代码示例:

/*eslint require-await: "error"*/
async function foo() {
await doSomething();
}
bar(async () => {
await doSomething();
});
function foo() {
doSomething();
}
bar(() => {
doSomething();
});
// Allow empty functions.
async function noop() {}

相关内容

  • 没有找到相关文章

最新更新