谷歌云函数http触发foreach循环问题

时间:2019-05-03 02:51:28

标签: javascript firebase google-cloud-firestore google-cloud-functions

我在云函数中有一个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)
        })

以下是与所有console.logs一起存储的相应日志

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 个答案:

答案 0 :(得分:1)

由于要并行执行几个异步任务(对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仅返回了一个文档(“带有该游戏图钉的文档只有一个”),则可以使用QuerySnapshot的docs属性,该属性返回“ 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);
      });
  });
});