我在PWA中使用以下代码根据文档计算Firebase实时数据库服务器的客户端时钟偏差: -
var offsetRef = firebase.database().ref(".info/serverTimeOffset");
offsetRef.on("value", function(snap) {
var offset = snap.val();
var estimatedServerTimeMs = new Date().getTime() + offset;
});
然而,问题是在某些设备上我得到奇怪的值,如-13181用于偏移,使其关闭差不多13秒!因此,该设备上的倒数计时器20秒从7秒开始,因为实际上偏移量要低得多。昨天,一台机器一直保持上述价值(-13181),尽管它早先工作正常。是否有任何理由说明同一网络上的设备会报告时间偏移值的巨大差异?我该如何解决这个问题?在不同设备上同步的倒数计时器对我的应用来说非常关键。
答案 0 :(得分:1)
昨天从我们的对话中添加了上下文,你说:
我们制作了一个测验应用程序,即使是成千上万的人也可以参与其中 实时,所以每个人都必须在倒计时看到相同的价值 计时器。我们的逻辑工作得非常好,除了事实 我很少得到奇怪的偏移值。
尽可能地,您不希望依赖客户的时钟。根据人们的网络质量和与服务器的距离,已经存在一些不可避免的差异,正如您所见,添加不可靠的本地时钟会加剧这一点。在线游戏的时间安排不是一项小任务,我不会声称拥有最佳解决方案,但这里有一个建议:
拥有真实的来源,可能是服务器,它可以跟踪游戏中剩余的时间并在数据库中对其进行更新。您可以使用Firebase Admin SDK从您的服务器访问数据库,这可能就是您现在正在输入时间戳的方式。
从Admin SDK写入数据库将如下所示:
admin.database().ref(".info/timeRemaining").set({
time_remaining: time_remaining
});
time_remaining
将是您每秒更新的时间。
然后在客户端上,而不是跟踪偏移量,你只剩下剩余的时间。
var offsetRef = firebase.database().ref(".info/timeRemaining");
offsetRef.on("value", function(snap) {
var offset = snap.val();
// do what you will
});
然后你可以在客户端上制定以0结束游戏的规则。当然开发人员可以找到解决方法,所以如果可能的话,最好包括一个服务器检查。如果客户端也在写入数据库,但您不希望它们在时间限制过后能够使用,则可以选择使用规则。现在,根据您的数据结构,您的规则会有所不同。我只是推测将写入应用于".info"
的任何孩子,这可能不是你需要的。
{
"rules": {
".info": {
"$info": {
".read": "auth != null",
// writes can only happen before the timer reaches 0
".write": "data.parent().child('time_remaining').val() > 0"
}
}
}
}
此规则仅允许用户在time_remaining
的值大于0时写入该位置。如果他们在此之后尝试写入,则会返回错误,您可以处理在客户端上显示此错误。