编辑:删除无关的代码,以提高可读性,编辑2:将示例简化为仅uploadGameRound函数,并添加日志输出的次数。
我正在开发一款移动多人字游戏,之前我使用过Firebase实时数据库,除了冷启动之外,它的性能也相当出色。保存更新的游戏和设置统计数据最多需要几秒钟。最近,我决定对我的游戏数据和玩家统计数据/顶级列表使用Firestore,主要是因为更高级的查询和自动缩放,而不需要手动分片。现在我已经做了一些关于Firestore的工作,但是保存一个更新的游戏和更新一些统计数据所花费的时间实在是太荒谬了。我在游戏更新前3-4分钟内平均计时,添加了统计数据,所有数据都可以在数据库中为其他客户提供,并可在web界面中查看。我猜测并希望这是因为我在实现中搞砸了一些事情,但是这些事务都经过了,并且没有任何警告或其他任何事情可以真正进行。查看云函数日志,函数调用到完成日志语句的总时间似乎超过了一分钟,但在相同的3-4分钟等待数据之后,日志才会出现。
这是它的代码。如果有人有时间看一看,也许发现出了什么问题,我会非常感激的!
这个函数是从Unity:调用的
exports.uploadGameRound = functions.https.onCall((roundUploadData, response) => {
console.log("UPLOADING GAME ROUND. TIME: ");
var d = new Date();
var n = d.toLocaleTimeString();
console.log(n);
// CODE REMOVED FOR READABILITY. JUST PREPARING SOME VARIABLES TO USE BELOW. NOTHING HEAVY, NO DATABASE TRANSACTIONS. //
// Get a new write batch
const batch = firestoreDatabase.batch();
// Save game info to activeGamesInfo
var gameInfoRef = firestoreDatabase.collection('activeGamesInfo').doc(gameId);
batch.set(gameInfoRef, gameInfo);
// Save game data to activeGamesData
const gameDataRef = firestoreDatabase.collection('activeGamesData').doc(gameId);
batch.set(gameDataRef, { gameDataCompressed: updatedGameDataGzippedString });
if (foundWord !== undefined && foundWord !== null) {
const wordId = foundWord.timeStamp + "_" + foundWord.word;
// Save word to allFoundWords
const wordRef = firestoreDatabase.collection('allFoundWords').doc(wordId);
batch.set(wordRef, foundWord);
exports.incrementNumberOfTimesWordFound(gameInfo.language, foundWord.word);
}
console.log("COMMITTING BATCH. TIME: ");
var d = new Date();
var n = d.toLocaleTimeString();
console.log(n);
// Commit the batch
batch.commit().then(result => {
return gameInfoRef.update({ roundUploaded: true }).then(function (result2) {
console.log("DONE COMMITTING BATCH. TIME: ");
var d = new Date();
var n = d.toLocaleTimeString();
console.log(n);
return;
});
});
});再一次,任何帮助理解这种奇怪的行为是非常感谢的!
发布于 2020-12-08 11:19:41
好吧,现在我发现了这个问题,我想我应该和大家分享一下:
只需在批处理提交之前添加一个返回语句,就可以修复函数,并将时间从4分钟缩短到不到1秒:
RETURN batch.commit().then(result => {
return gameInfoRef.update({ roundUploaded: true }).then(function (result2) {
console.log("DONE COMMITTING BATCH. TIME: ");
var d = new Date();
var n = d.toLocaleTimeString();
console.log(n);
return;
});
});发布于 2020-12-07 16:59:16
您的函数不会返回与发送给客户端应用程序的数据一起解析的承诺。如果没有返回的承诺,它将立即返回,不能保证任何挂起的异步工作将正确终止。
在单个承诺上调用then并不足以处理承诺。您可能需要在commit()和其他函数(如incrementNumberOfTimesWordFound )之间进行大量异步工作。您将需要正确地处理所有的承诺,并确保您的整体功能只返回一个承诺,该承诺在所有工作完成后得到解决。
我强烈建议花点时间来学习在JavaScript中承诺是如何工作的--这对于编写有效的函数至关重要。如果没有充分的理解,事情就会以奇怪的方式出现问题,或者根本不会出错。
https://stackoverflow.com/questions/65172430
复制相似问题