Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/460.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Nodejs Firebase事务-超过最大调用堆栈大小_Javascript_Node.js_Firebase_Firebase Realtime Database_Google Cloud Functions - Fatal编程技术网

Javascript Nodejs Firebase事务-超过最大调用堆栈大小

Javascript Nodejs Firebase事务-超过最大调用堆栈大小,javascript,node.js,firebase,firebase-realtime-database,google-cloud-functions,Javascript,Node.js,Firebase,Firebase Realtime Database,Google Cloud Functions,我有一个云函数,它使用事务更新游戏中的玩家。当/players为空时,我试图返回一个映射,但得到“超出了最大调用堆栈大小” 以下是我的云功能: export const addUserToGame = functions.https.onCall((data, context) => { // Expected inputs - game_id(from data) and UID(from context) if (context.auth == null) {

我有一个云函数,它使用事务更新游戏中的玩家。当/players为空时,我试图返回一个映射,但得到“超出了最大调用堆栈大小”

以下是我的云功能:

export const addUserToGame = functions.https.onCall((data, context) => {

    // Expected inputs - game_id(from data) and UID(from context)

    if (context.auth == null) {
        return {
            "status": 403,
            "message": "You are not authorized to access this feature"
        };
    }

    const uid = context.auth.uid;
    const game_id = data.game_id;

    let gameIDRef = gamesRef.child(game_id);
    return gameIDRef.once("value", function (snapshot) {

        let players: Map<String, Number> = snapshot.child("players").val();
        let max_players: Number = snapshot.child("max_players").val();
        if (players != null && players.has(uid)) {
            return {
                "status": 403,
                "message": "Player already in the game"
            }
        } else if (players != null && players.size >= max_players) {
            return {
                "status": 403,
                "message": "Game is already full"
            }
        } else {
            let playersNodeRef = gamesRef.child(game_id).child("players");
            return playersNodeRef.transaction(t => {

                if (t === null) {
                    return new Map<String, Number>().set(uid, 1);//trying to set a map with the player data, when the /players is null
                } else {
                    let playersData: Map<String, Number> = t;
                    if (playersData.size >= max_players) { // rechecking
                        return;
                    } else {
                        playersData.set(uid, 1);
                        return playersData;
                    }
                }

            }).then(result => {
                if (result.committed) { // if true there is a commit and the transaction went through
                    return {
                        "status": 200,
                        "message": "User added to game successfully"
                    }
                } else {
                    return {
                        "status": 403,
                        "message": "Unable to add user at this time. Please try again"
                    }
                }
            }).catch(error => {
                return {
                    "status": 403,
                    "message": error
                }
            });
        }
    });
});


您的问题很可能是由于返回了一个复杂的JavaScript对象,请参阅

此外请注意,您应该使用该方法的promise版本,因为在可调用的云函数中,您必须返回与要发送回客户端的数据对象解析的promise

而不是做

return gameIDRef.once("value", function (snapshot) {...});

有了它,您将能够正确构建要返回的。另外,在处理
players
值周围的不同情况时,不要返回将在
中处理的JavaScript对象。然后((result)=>{…})
块(这不是必需的,也不是真正合乎逻辑的),抛出将在
catch()
块中处理的错误

大致如下:

export const addUserToGame = functions.https.onCall((data, context) => {
  // Expected inputs - game_id(from data) and UID(from context)

  if (context.auth == null) {
    return {
      status: 403,
      message: 'You are not authorized to access this feature',
    };
    // IMHO better to do  throw new functions.https.HttpsError('...', ...);
  }

  const uid = context.auth.uid;
  const game_id = data.game_id;

  let gameIDRef = gamesRef.child(game_id);
  return gameIDRef
    .once('value')
    .then((snapshot) => {
      let players: Map<String, Number> = snapshot.child('players').val();
      let max_players: Number = snapshot.child('max_players').val();

      if (players != null && players.has(uid)) {
        throw new Error('Player already in the game');
      } else if (players != null && players.size >= max_players) {
        throw new Error('Game is already full');
      } else {
        let playersNodeRef = gamesRef.child(game_id).child('players');
        return playersNodeRef.transaction((t) => {
          if (t === null) {
            return new Map<String, Number>().set(uid, 1); //trying to set a map with the player data, when the /players is null
          } else {
            let playersData: Map<String, Number> = t;
            if (playersData.size >= max_players) {
              // rechecking
              return;
            } else {
              playersData.set(uid, 1);
              return playersData;
            }
          }
        });
      }
    })
    .then((result) => {
      if (result.committed) {
        // if true there is a commit and the transaction went through
        return {
          status: 200,
          message: 'User added to game successfully',
        };
      } else {
        // probably throw an error here
        return {
          status: 403,
          message: 'Unable to add user at this time. Please try again',
        };
      }
    })
    .catch((error) => {
      if (error.message === 'Player already in the game') {
        throw new functions.https.HttpsError('...', error.message);
      } else if (error.message === 'Game is already full') {
        throw new functions.https.HttpsError('...', error.message);
      } else {
        throw new functions.https.HttpsError('internal', error.message);
      }
    });
});
export const addUserToGame=functions.https.onCall((数据,上下文)=>{
//预期输入-游戏id(来自数据)和UID(来自上下文)
if(context.auth==null){
返回{
现状:403,
消息:“您无权访问此功能”,
};
//我最好抛出新函数。https.HttpsError(“…”,…);
}
const uid=context.auth.uid;
const game\u id=data.game\u id;
让gameIDRef=gamesRef.child(游戏id);
返回gameIDRef
.once('值')
。然后((快照)=>{
让玩家:Map=snapshot.child('players').val();
让max_players:Number=snapshot.child('max_players').val();
if(players!=null&&players.has(uid)){
抛出新错误(“玩家已在游戏中”);
}else if(players!=null&&players.size>=max\u players){
抛出新错误(“游戏已满”);
}否则{
let playersNodeRef=gamesRef.child(game_id).child('players');
return playersNodeRef.transaction((t)=>{
如果(t==null){
return new Map().set(uid,1);//当/players为空时,尝试使用播放器数据设置地图
}否则{
让playersData:Map=t;
如果(playersData.size>=最大玩家数){
//复查
返回;
}否则{
playersData.set(uid,1);
返回playersData;
}
}
});
}
})
。然后((结果)=>{
if(result.committed){
//如果为true,则存在提交,并且事务已通过
返回{
现状:200,
消息:“用户已成功添加到游戏”,
};
}否则{
//可能会在这里抛出一个错误
返回{
现状:403,
消息:“此时无法添加用户。请重试”,
};
}
})
.catch((错误)=>{
如果(error.message==='玩家已在游戏中'){
抛出新函数.https.HttpsError(“…”,error.message);
}else if(error.message==='游戏已满'){
抛出新函数.https.HttpsError(“…”,error.message);
}否则{
抛出新函数.https.HttpsError('internal',error.message);
}
});
});

有关如何处理可调用云函数中的错误的更多详细信息,请参阅。

您的问题很可能来自返回复杂JavaScript对象的事实,请参阅

此外请注意,您应该使用该方法的promise版本,因为在可调用的云函数中,您必须返回与要发送回客户端的数据对象解析的promise

而不是做

return gameIDRef.once("value", function (snapshot) {...});

有了它,您将能够正确构建要返回的。另外,在处理
players
值周围的不同情况时,不要返回将在
中处理的JavaScript对象。然后((result)=>{…})
块(这不是必需的,也不是真正合乎逻辑的),抛出将在
catch()
块中处理的错误

大致如下:

export const addUserToGame = functions.https.onCall((data, context) => {
  // Expected inputs - game_id(from data) and UID(from context)

  if (context.auth == null) {
    return {
      status: 403,
      message: 'You are not authorized to access this feature',
    };
    // IMHO better to do  throw new functions.https.HttpsError('...', ...);
  }

  const uid = context.auth.uid;
  const game_id = data.game_id;

  let gameIDRef = gamesRef.child(game_id);
  return gameIDRef
    .once('value')
    .then((snapshot) => {
      let players: Map<String, Number> = snapshot.child('players').val();
      let max_players: Number = snapshot.child('max_players').val();

      if (players != null && players.has(uid)) {
        throw new Error('Player already in the game');
      } else if (players != null && players.size >= max_players) {
        throw new Error('Game is already full');
      } else {
        let playersNodeRef = gamesRef.child(game_id).child('players');
        return playersNodeRef.transaction((t) => {
          if (t === null) {
            return new Map<String, Number>().set(uid, 1); //trying to set a map with the player data, when the /players is null
          } else {
            let playersData: Map<String, Number> = t;
            if (playersData.size >= max_players) {
              // rechecking
              return;
            } else {
              playersData.set(uid, 1);
              return playersData;
            }
          }
        });
      }
    })
    .then((result) => {
      if (result.committed) {
        // if true there is a commit and the transaction went through
        return {
          status: 200,
          message: 'User added to game successfully',
        };
      } else {
        // probably throw an error here
        return {
          status: 403,
          message: 'Unable to add user at this time. Please try again',
        };
      }
    })
    .catch((error) => {
      if (error.message === 'Player already in the game') {
        throw new functions.https.HttpsError('...', error.message);
      } else if (error.message === 'Game is already full') {
        throw new functions.https.HttpsError('...', error.message);
      } else {
        throw new functions.https.HttpsError('internal', error.message);
      }
    });
});
export const addUserToGame=functions.https.onCall((数据,上下文)=>{
//预期输入-游戏id(来自数据)和UID(来自上下文)
if(context.auth==null){
返回{
现状:403,
消息:“您无权访问此功能”,
};
//我最好抛出新函数。https.HttpsError(“…”,…);
}
const uid=context.auth.uid;
const game\u id=data.game\u id;
让gameIDRef=gamesRef.child(游戏id);
返回gameIDRef
.once('值')
。然后((快照)=>{
让玩家:Map=snapshot.child('players').val();
让max_players:Number=snapshot.child('max_players').val();
if(players!=null&&players.has(uid)){
抛出新错误(“玩家已在游戏中”);
}else if(players!=null&&players.size>=max\u players){
抛出新错误(“游戏已满”);
}否则{
let playersNodeRef=gamesRef.child(game_id).child('players');
return playersNodeRef.transaction((t)=>{
如果(t==null){
return new Map().set(uid,1);//当/players为空时,尝试使用播放器数据设置地图
}否则{
让playersData:Map=t;
如果(playersData.size>=最大玩家数){
//复查
返回;
}否则{
playersData.set(uid,1);
返回playersData;
}
}
});
}
})
。然后((结果)=>{
if(result.committed){
//如果为true,则存在提交,并且事务已通过
返回{
现状:200,
消息:“用户已成功添加到游戏”,
};
}否则{
//可能会在这里抛出一个错误
返回{
export const addUserToGame = functions.https.onCall((data, context) => {
  // Expected inputs - game_id(from data) and UID(from context)

  if (context.auth == null) {
    return {
      status: 403,
      message: 'You are not authorized to access this feature',
    };
    // IMHO better to do  throw new functions.https.HttpsError('...', ...);
  }

  const uid = context.auth.uid;
  const game_id = data.game_id;

  let gameIDRef = gamesRef.child(game_id);
  return gameIDRef
    .once('value')
    .then((snapshot) => {
      let players: Map<String, Number> = snapshot.child('players').val();
      let max_players: Number = snapshot.child('max_players').val();

      if (players != null && players.has(uid)) {
        throw new Error('Player already in the game');
      } else if (players != null && players.size >= max_players) {
        throw new Error('Game is already full');
      } else {
        let playersNodeRef = gamesRef.child(game_id).child('players');
        return playersNodeRef.transaction((t) => {
          if (t === null) {
            return new Map<String, Number>().set(uid, 1); //trying to set a map with the player data, when the /players is null
          } else {
            let playersData: Map<String, Number> = t;
            if (playersData.size >= max_players) {
              // rechecking
              return;
            } else {
              playersData.set(uid, 1);
              return playersData;
            }
          }
        });
      }
    })
    .then((result) => {
      if (result.committed) {
        // if true there is a commit and the transaction went through
        return {
          status: 200,
          message: 'User added to game successfully',
        };
      } else {
        // probably throw an error here
        return {
          status: 403,
          message: 'Unable to add user at this time. Please try again',
        };
      }
    })
    .catch((error) => {
      if (error.message === 'Player already in the game') {
        throw new functions.https.HttpsError('...', error.message);
      } else if (error.message === 'Game is already full') {
        throw new functions.https.HttpsError('...', error.message);
      } else {
        throw new functions.https.HttpsError('internal', error.message);
      }
    });
});