我在云函数中有一个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一起存储的相应日志
已更新:
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)
})
})
})
答案 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);
});
});
});