如何从数组中获取ID列表,将每个项目与firestore中的ID匹配,并将相关数据的JSON返回到前端站点?



正如标题所说,我试图从数组中获取ID列表,将每个ID与firestore中的ID匹配,并将相关数据的json数组返回给前端站点。下面的代码返回一个空数组。

const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.getPlayerDataFromTokens = functions.https.onCall(async (data, context) => {
return new Promise((resolve, reject) => {
var db = admin.firestore();
const tokens = data.tokens;
let playerArray = [];
tokens.forEach((token) => {
const tokensToTokenData = db.collection("Football_Player_Data").where("Token", "==", token);
tokensToTokenData.get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
playerDataToken = doc.data()["Token"];
playerDataJersey = doc.data()["Jersey_Number"];
playerDataMultiplier = doc.data()["Multiplier"];
playerDataPlayerID = doc.data()["PlayerID"];
playerDataPosition = doc.data()["Position"];
playerDataTeam = doc.data()["Team"];
playerData = {
"Token": playerDataToken,
"PlayerID": playerDataPlayerID,
"Jersey_Number": playerDataJersey,
"Position": playerDataPosition,
"Team": playerDataTeam,
"Multiplier": playerDataMultiplier
};
playerArray.push(playerData);

});
})
.catch((error) => {
playerArray = error;
console.log("Error getting documents: ", error)
reject(playerArray);
});
})
resolve(JSON.stringify(playerArray));
});
})

根据你的代码,你是基于一个非常过时的教程来构建这个。

在Firebase Functions V1.0.0(2018年4月)中,删除了functions.config().firebase。它现在解析为undefined,以便现代admin.initializeApp()(没有参数)正常工作。当以这种方式调用时,Admin SDK将根据适当的环境变量进行初始化。

接下来,您将使用显式承诺构造反模式。简而言之,不要将代码包装在new Promise((resolve, reject) => {})中。

因为这个函数代码很可能被部署到Google Cloud functions,它运行在Node 10/12/14上,你可以使用现代ES2017语法,如async/await,解构模式,import,let,constPromise.all

这意味着你的脚本的顶部包含:

import * as admin from "firebase-admin";
import * as functions from "firebase-functions";
admin.initializeApp();

当你需要为每个给定的令牌获取玩家列表时,你可以将这个逻辑分解成它自己的函数:

/**
* For the given token, return an array of players linked with
* that token.
*/
async function getFootballPlayersWithToken(db, token) {
const playersWithTokenQuerySnapshot = await db
.collection("Football_Player_Data")
.where("Token", "==", token)
.get();
if (playersWithTokenQuerySnapshot.empty) {
console.log("Given token did not match any players: ", token);
return []; // or throw error
}

const playerArray = await Promise.all(
playersWithTokenQuerySnapshot.docs
.map((playerDoc) => {
const { Token, Jersey_Number, Multiplier, PlayerID, Position, Team } = playerDoc.data();
return { Token, Jersey_Number, Multiplier, PlayerID, Position, Team };
});
);

return playerArray;
}
在上面的代码块中,重要的是要注意playersWithTokenQuerySnapshot是一个QuerySnapshot对象,而不是一个数组。虽然forEachQuerySnapshot对象上可用,但要使用普通的Array方法,如.map.reduce,您需要使用docs属性代替。

这使得你的云函数:

exports.getPlayerDataFromTokens = functions.https.onCall(async (data, context) => {
const { tokens } = data;

try {
const db = admin.firestore();

const playersGroupedByTokenArray = await Promise.all(
tokens.map(token => getFootballPlayersWithToken(db, token))
);

// playersGroupedByTokenArray is an array of arrays
// e.g. [[token1Player1, token1Player2], [token2Player1], [], ...]
// flatten this array

// Node 12+:
// const playerArray = playersGroupedByTokenArray.flat()
// Node 10+:
const playerArray = [];
playersGroupedByTokenArray.forEach(
groupOfPlayers => playerArray.push(...groupOfPlayers)
);

return playerArray;
} catch (error) {
console.error("Error finding players for one or more of these tokens: ", tokens.join(", "))
throw new functions.https.HttpsError(
"unknown",
"Could not get players for one or more of the tokens provided",
error.code || error.message
);
}
);

如上面的代码块所示,为了正确处理错误,必须将它们包装在HttpsError中。

如果一个令牌只返回一个玩家,你可以把上面的get玩家函数调整为以下内容,然后根据需要编辑你的云函数:

/**
* For the given token, return the matching player.
*/
async function getFootballPlayerByToken(db, token) {
const playersWithTokenQuerySnapshot = await db
.collection("Football_Player_Data")
.where("Token", "==", token)
.get();
if (playersWithTokenQuerySnapshot.empty) {
console.log("Given token did not match any players: ", token);
return null; // or throw error
}

const playerDoc = playersWithTokenQuerySnapshot.docs[0];
const { Token, Jersey_Number, Multiplier, PlayerID, Position, Team } = playerDoc.data();
return { Token, Jersey_Number, Multiplier, PlayerID, Position, Team };
}

最新更新