Google Cloud функция http триггер проблема с циклом foreach - PullRequest
0 голосов
/ 03 мая 2019

У меня есть http-триггер в облачных функциях, который, кажется, работает, однако я получаю некоторые журналы, которые заставляют меня подвергать сомнению цикл foreach.

Вопрос: Есть ли лучший способ написать эту функцию, чтобы не использовать цикл foreach?

Функция:

const gamePin = req.body.gamepin
        const numPlayers = req.body.playercount.toString()

        var getGame = admin.firestore().collection('games')
        getGame = getGame.where('gid', '==', gamePin).get()
        .then(snapshot => {
            if (!snapshot.empty) {

                console.log(`BODY: ${JSON.stringify(req.body)}`);

                snapshot.forEach(doc => {
                    let data = doc.data()
                    data.id = doc.id

                    console.log(`DOC DATA: ${JSON.stringify(data)}`);

                    const currentNumPlayers = data.playercount
                    console.log(`currentNumPlayers: ${JSON.stringify(currentNumPlayers)}`);

                    const newPlayerCount = +numPlayers + +currentNumPlayers
                    console.log(`newPlayerCount: ${JSON.stringify(newPlayerCount)}`);

                    const newPlayerCountToString = newPlayerCount.toString()
                    console.log(`newPlayerCountToString: ${JSON.stringify(newPlayerCountToString)}`);

                    var updateGame = admin.firestore().collection('games').doc(data.id)
                    updateGame.update({
                        playercount: newPlayerCountToString
                    }).then(res => {
                        console.log(`COMPLETED UPDATE: ${JSON.stringify(res)}`);
                        res.send({ status: 200, message: 'Game: updated.', pin: gamePin })
                    }).catch(err => {
                        console.log(`ERROR IN QUERY: ${JSON.stringify(err)}`);
                        res.status(500).send(err)
                    })

                })

            } else {
                console.log('could not find a match ', snapshot)
                res.send({ status: 400, message: 'Error. could not find a match' })
            }
        })
        .catch(error => {
            console.log(error)
            res.status(500).send(error)
        })

Вот соответствующие журналы, чтобы пойтивместе со всеми этими консольными журналами

enter image description here

ОБНОВЛЕНО:

exports.addPlayerToGame = functions.https.onRequest((req, res) => {
    return cors(req, res, () => {


        // Check for POST request
        if (req.method !== "POST") {
            res.status(400).send('Please send a POST request');
            return;
        }
        const gamePin = req.body.gamepin
        const numPlayers = req.body.playercount.toString()

        var getGame = admin.firestore().collection('games')
        getGame = getGame.where('gid', '==', gamePin).get()
        .then(snapshot => {
            if (!snapshot.empty) {

                console.log(`BODY: ${JSON.stringify(req.body)}`);
                const doc = snapshot.docs[0];
                let data = doc.data()
                data.id = doc.id

                const currentNumPlayers = data.playercount
                console.log(`currentNumPlayers: ${JSON.stringify(currentNumPlayers)}`);

                const newPlayerCount = +numPlayers + +currentNumPlayers
                console.log(`newPlayerCount: ${JSON.stringify(newPlayerCount)}`);

                const newPlayerCountToString = newPlayerCount.toString()
                console.log(`newPlayerCountToString: ${JSON.stringify(newPlayerCountToString)}`);

                return admin.firestore().collection('games').doc(data.id)
                    .update({
                        playercount: newPlayerCountToString
                    })
                    .then((res) => {
                        console.log(`COMPLETED UPDATE: ${JSON.stringify(res)}`);
                        res.send({
                            status: 200,
                            message: 'Game: updated.',
                            pin: gamePin
                        });
                    })
                    .catch(err => {
                        console.log(`ERROR IN QUERY: ${JSON.stringify(err)}`);
                        // throw new Error(err);
                        res.status(500).send(err)
                    });

            } else {
                console.log('could not find a match ', snapshot)
                res.send({ status: 400, message: 'Error. could not find a match' })
            }

            console.log(`END:`);
        })
        .catch(error => {
            console.log(error)
            res.status(500).send(error)
        })

    })

})

1 Ответ

1 голос
/ 03 мая 2019

Поскольку вы хотите параллельно выполнять несколько асинхронных задач (вызов метода update(), который возвращает Promise), вам нужно использовать Promise.all(), какследует:

var getGame = admin.firestore().collection('games');
getGame = getGame
  .where('gid', '==', gamePin)
  .get()
  .then(snapshot => {
    if (!snapshot.empty) {
      console.log(`BODY: ${JSON.stringify(req.body)}`);

      const promises = [];

      snapshot.forEach(doc => {
        let data = doc.data();
        data.id = doc.id;

        console.log(`DOC DATA: ${JSON.stringify(data)}`);

        const currentNumPlayers = data.playercount;
        console.log(`currentNumPlayers: ${JSON.stringify(currentNumPlayers)}`);

        const newPlayerCount = +numPlayers + +currentNumPlayers;
        console.log(`newPlayerCount: ${JSON.stringify(newPlayerCount)}`);

        const newPlayerCountToString = newPlayerCount.toString();
        console.log(
          `newPlayerCountToString: ${JSON.stringify(newPlayerCountToString)}`
        );

        var updateGame = admin
          .firestore()
          .collection('games')
          .doc(data.id);

        promises.push(
          updateGame.update({
            playercount: newPlayerCountToString
          })
        );
      });

      return Promise.all(promises)
        .then(results => {
          console.log(`COMPLETED UPDATE: ${JSON.stringify(res)}`);
          res.send({
            status: 200,
            message: 'Game: updated.',
            pin: gamePin
          });
        })
        .catch(err => {
          console.log(`ERROR IN QUERY: ${JSON.stringify(err)}`);
          throw new Error(err);
        });
    } else {
      console.log('could not find a match ', snapshot);
      throw new Error('Error. could not find a match');
    }
  })
  .catch(error => {
    console.log(error);
    res.status(500).send(error);
  });

Обновление после вашего комментария : Если вы точно знаете, что Query ("возвращает только один документ)есть только один документ с этим игровым значком "), вы можете использовать свойство docs объекта QuerySnapshot, которое возвращает" массив всех документов в QuerySnapshot "и выполняет следующие действия:

var getGame = admin.firestore().collection('games');
getGame = getGame
  .where('gid', '==', gamePin)
  .get()
  .then(snapshot => {
    if (!snapshot.empty) {
      console.log(`BODY: ${JSON.stringify(req.body)}`);

      const doc = snapshot.docs[0];

      let data = doc.data();
      data.id = doc.id;

      const currentNumPlayers = data.playercount;
      const newPlayerCount = +numPlayers + +currentNumPlayers;
      const newPlayerCountToString = newPlayerCount.toString();


      return admin.firestore().collection('games').doc(data.id)
      .update({
            playercount: newPlayerCountToString
      })
      .then(() => {
          console.log(`COMPLETED UPDATE: ${JSON.stringify(res)}`);
          res.send({
            status: 200,
            message: 'Game: updated.',
            pin: gamePin
          });
      })
      .catch(err => {
          console.log(`ERROR IN QUERY: ${JSON.stringify(err)}`);
          throw new Error(err);
      });
    } else {
      console.log('could not find a match ', snapshot);
      throw new Error('Error. could not find a match');
    }
  })
  .catch(error => {
    console.log(error);
    res.status(500).send(error);
  });

Второе обновление , см. Комментарии в коде:

exports.addPlayerToGame = functions.https.onRequest((req, res) => {
  return cors(req, res, () => {
    // Check for POST request
    if (req.method !== 'POST') {
      res.status(400).send('Please send a POST request');
    }

    const gamePin = req.body.gamepin;
    const numPlayers = req.body.playercount.toString();

    admin   //Here I would not use a getGame variable
      .firestore()
      .collection('games')
      .where('gid', '==', gamePin)
      .get()
      .then(snapshot => {
        if (!snapshot.empty) {
          console.log(`BODY: ${JSON.stringify(req.body)}`);

          const doc = snapshot.docs[0];
          let data = doc.data();
          data.id = doc.id;

          const currentNumPlayers = data.playercount;
          console.log(
            `currentNumPlayers: ${JSON.stringify(currentNumPlayers)}`
          );

          const newPlayerCount = +numPlayers + +currentNumPlayers;
          console.log(`newPlayerCount: ${JSON.stringify(newPlayerCount)}`);

          const newPlayerCountToString = newPlayerCount.toString();
          console.log(
            `newPlayerCountToString: ${JSON.stringify(newPlayerCountToString)}`
          );

          return admin
            .firestore()
            .collection('games')
            .doc(data.id)
            .update({
              playercount: newPlayerCountToString
            })
            .then(() => { //Here, I don't understand why do you return res. The update method returns an empty Promise so just do .then(() => {}}
              console.log(`COMPLETED UPDATE`);  //Here don't use res, as it is the Response object and represents the HTTP response that an Express app sends when it gets an HTTP request
              res.send({
                status: 200,
                message: 'Game: updated.',
                pin: gamePin
              });
            })
            .catch(err => {
              console.log(`ERROR IN QUERY: ${JSON.stringify(err)}`);
              // throw new Error(err);
              res.status(500).send(err); //I am not sure what is better... throwing an Error or sending back a 500 response code.
            });
        } else {
          console.log('could not find a match ', snapshot);
          res.send({ status: 400, message: 'Error. could not find a match' });
        }

        console.log(`END:`);
      })
      .catch(error => {
        console.log(error);
        res.status(500).send(error);
      });
  });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...