Cloud Function写入FireStore延迟,需等待下一次实例触发才执行写入
核心问题原因
你遇到的延迟写入问题本质是云函数异步操作未正确向运行时返回Promise导致的:
Cloud Function/PubSub触发的函数在执行时,如果未将异步操作的Promise返回给运行时,运行时会认为同步代码执行完成就终止函数实例(将实例冻结休眠),所有未完成的异步IO(比如你的Firestore读写)会被挂起,直到下一次该实例被唤醒触发新的请求时,才会继续执行上一次挂起的异步逻辑,这就是你看到的两次写入在第二次实例触发后同时完成的原因。
修复方案1:返回异步Promise链
将你的Firestore操作整段Promise链直接return即可,让运行时知道还有异步操作未完成,会等待所有Promise完成后再冻结实例:
if (jsonData.Event == "TEST") { var msg = jsonData.Value; var timeOfReception = new Date(); // 重点:返回整个Promise链给云函数运行时 return docRef .get() .then(function (doc) { if (doc.exists) { return docRef.update({ LastGesture: msg, }).then(function() { console.log("Write completed") }).catch(function(error) { console.error("Write failed: "+error) }); } else { console.log("No such document!"); } }) .catch(function (error) { console.log("Error getting document:", error); }); }
修复方案2:改用async/await写法(推荐,可读性更高)
如果你的云函数运行时支持Node.js 8及以上版本,用async/await写法可以避免漏写Promise返回的问题:
// 函数外层先声明async exports.yourFunctionName = async (pubSubEvent, context) => { const jsonData = JSON.parse(Buffer.from(pubSubEvent.data, 'base64').toString()); if (jsonData.Event == "TEST") { const msg = jsonData.Value; const timeOfReception = new Date(); try { const doc = await docRef.get(); if (doc.exists) { await docRef.update({ LastGesture: msg }); console.log("Write completed"); } else { console.log("No such document!"); } } catch (error) { console.error("操作失败:", error); } } };
补充排查方向
- 确认云函数运行时版本,避免使用已废弃的Node.js版本,不同版本对异步逻辑的处理规则有差异
- 可以在日志中打印每条PubSub消息的唯一标识,确认写入操作和触发事件的对应关系,避免混淆不同请求的日志
- 若修复后仍有延迟,可检查Firestore所在区域是否和云函数部署区域一致,跨区域调用会增加IO延迟
内容的提问来源于stack exchange,提问作者Antoine Turcotte
相关产品推荐
相关产品推荐

