首页 > 解决方案 > 我在云功能中的计时器在第二次通话后停止

问题描述

我的应用程序是一个多人游戏,玩家可以在其中创建一个会话,每个会话都有一个独特的sessionID并且包含许多回合,并且每个回合都有自己的计时器。

我做了一个用于实现计时器的云功能。它工作得很好,但是如果session1启动它的计时器然后session2启动它自己的计时器。发生的事情是计时器session1停止了!

我用javascript编写的函数,它每秒更新firebase中实时数据库中的计时器。

构建我的实时数据库

云功能代码

exports.RoundTimerS = functions.database.ref('/Sessions/{sessionid}/onCamera')
.onCreate((snap, context) => {
    var SessionID = context.params.sessionid
    sessionref4 = "/Sessions/".concat(SessionID);
    sessionref4 = sessionref4.concat("/Timer");

    sessionref5 = "/Sessions/".concat(SessionID);
    sessionref5 = sessionref5.concat("/numOfPlayers");

    sessionref6 = "/Sessions/".concat(SessionID);
    sessionref6 = sessionref6.concat("/NumberOfFinish");

    Roundtimer = 60 //60s
 
    var player = 0
    var db = admin.database();
    var ref = db.ref(sessionref5); 
    var ref2 = db.ref(sessionref6);

    ref.once("value", function (snapshot2) {
        player = snapshot2.val() 
    }, function (errorObject) {
        console.log("The read failed: " + errorObject.code);
    });

    var Timer = setInterval(function () {
        admin.database()
            .ref(sessionref4 + "/Roundtimer1").set(Roundtimer)
        ref2.once("value", function (snapshot) {
            if (snapshot.numChildren() == player) {                   
                clearInterval(Timer)//Stop timer 
            }
        }, function (errorObject) {
            console.log("The read failed: " + errorObject.code);
        });

        if (Roundtimer <= 0) { //Round Timer finish 
            admin.database()
                .ref(sessionref4 + "/Roundtimer1").set(Roundtimer) 
            clearInterval(Timer)//Stop timer 
        }

        Roundtimer -= 1

标签: javascriptfirebasefirebase-realtime-databasegoogle-cloud-functions

解决方案


Cloud Functions 会一直运行到}它们的代码结束,也就是你的计时器结束之前。因此,您的容器在计时器完成之前被回收。

如果您希望容器为任何异步操作保持活动状态,则需要返回一个承诺,该承诺在所有工作完成后解决。

exports.RoundTimerS = functions.database.ref('/Sessions/{sessionid}/onCamera')
.onCreate((snap, context) => {
  return new Promise((resolve, reject) => {
    var SessionID = context.params.sessionid
    sessionref4 = "/Sessions/".concat(SessionID);
    sessionref4 = sessionref4.concat("/Timer");

    sessionref5 = "/Sessions/".concat(SessionID);
    sessionref5 = sessionref5.concat("/numOfPlayers");

    sessionref6 = "/Sessions/".concat(SessionID);
    sessionref6 = sessionref6.concat("/NumberOfFinish");

    Roundtimer = 60 //60s
 
    var player = 0
    var db = admin.database();
    var ref = db.ref(sessionref5); 
    var ref2 = db.ref(sessionref6);

    ref.once("value", function (snapshot2) {
        player = snapshot2.val() 
    }, function (errorObject) {
        console.log("The read failed: " + errorObject.code);
    });

    var Timer = setInterval(function () {
        db.ref(sessionref4 + "/Roundtimer1").set(Roundtimer)
        ref2.once("value", function (snapshot) {
            if (snapshot.numChildren() == player) {                   
                clearInterval(Timer)//Stop timer 
            }
        }, function (errorObject) {
            console.log("The read failed: " + errorObject.code);
        });

        if (Roundtimer <= 0) { //Round Timer finish 
            db.ref(sessionref4 + "/Roundtimer1").set(Roundtimer).then(() =
> {
              resolve(); // this seems to be where your timer is done
            })
            clearInterval(Timer)//Stop timer 
        }

        Roundtimer -= 1
        ...
  });

请注意,这并不意味着是复制/粘贴解决方案,而是您应该采取的方法的概述。这是:

  1. 返回一个承诺。
  2. 确定工作已完成。

我强烈建议您阅读 Cloud Functions 中的异步工作,因为在您控制住它之前,您会一直遇到问题。一些不错的资源:


推荐阅读