您好,我已经设置了Firebase功能,正在监视用户是否匹配。 所有部分都起作用,但是我又添加了一种方法 getUserDataById ,我想从用户那里获取更多数据,它返回未定义。 所以这就是我尝试过的:
exports.UserPressesLike = functions.database
.ref('/users/{userId}/matches/{otherUserId}')
.onCreate(async (snapshot, context) => {
// Grab the current value of what was written to the Realtime Database.
const original = snapshot.val();
const userId = context.params.userId;
const matchedUserId = context.params.otherUserId;
const a = await checkUserMatch(userId, matchedUserId);
if (a === true) {
console.log('Its a match');
addNewChat(userId, matchedUserId);
//create chat for both users
} else {
console.log('There is no match');
//do nothing
console.log(a);
}
return null;
});
checkUserMatch = async (userId, matchedUserId) => {
const isLiked = await admin
.database()
.ref('/users/' + matchedUserId + '/matches/' + userId)
.once('value')
.then(snapshot => {
// let tempuserId = snapshot.val();
// if()
let isLiked = snapshot.exists();
console.log(isLiked);
return isLiked;
})
.catch(error => {
console.log(error);
return snapshot;
});
return isLiked;
};
addNewChat = async (userId, matchedUserId) => {
const user1 = await getUserDataById(userId);
const user2 = await getUserDataById(matchedUserId);
console.log(JSON.stringify('User data: ' + user1));
const snapshot = await admin
.database()
.ref('/chats')
.push({
members: { [userId]: true, [matchedUserId]: true },
[userId]: { username: [user1.username] },
[matchedUserId]: { username: [user2.username] },
});
};
getUserDataById = async userId => {
const snapshot = await admin
.database()
.ref('/users/' + userId)
.once('value')
.then(childsnapshot => {
let data = childsnapshot.val();
return data;
});
};
但是我得到了错误:
TypeError: Cannot read property 'username' of undefined
at addNewChat (/srv/index.js:93:36)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
问题出在getUserDataById方法中。因为它返回未定义。 我在哪里弄错了?
答案 0 :(得分:1)
getUserDataById
返回undefined
您在异步功能中忘记了return snapshot
。 (但是,由于它是一个普通对象,而不是快照,因此我将其重命名)
getUserDataById = async userId => {
const userData = await admin
.database()
.ref('/users/' + userId)
.once('value')
.then(childsnapshot => {
let data = childsnapshot.val();
return data;
});
return userData;
};
但是,我将其简化为以下内容(与上述内容相同,但简洁明了):
getUserDataById = userId => {
return admin
.database()
.ref('/users/' + userId)
.once('value')
.then(childsnapshot => childsnapshot.val());
};
{username: {0: "Emilis"}}
的形式返回? {0: "Emilis"}
作为对象而不是数组返回是由Firebase在实时数据库中存储数组的方式引起的。在arrays on the Firebase Blog上有一篇非常全面的文章,涵盖了这些奇怪的地方,建议阅读。我将在这里总结关键的内容。
任何数组存储在实时数据库中时,将以其对象形式存储,其中{username: [user1.username] }
将存储为{username: {0: "someusername"} }
。由于JSON是无类型的,因此Realtime Database不再将其理解为数组。具有多个条目的数组也将存储为一个普通对象([value1, value2]
将变成{0: value1, 1: value2}
)。
当Firebase JavaScript SDK从实时数据库下载数据时,它会检查任何对象的键以获取大部分为连续的数字序列(0、1、2、3,...或0、1、3、4,)。 ..),如果检测到,则使用null
将其丢失的条目转换为数组。
由于{0: value1, 1: value2}
包含顺序键0
和1
,因此它将解析为[value1, value2]
。
由于{0: "someusername"}
不包含键序列,因此按原样返回。
要绕过此操作,请删除单个条目数组并直接使用其值(如下所示),或在客户端代码中将其显式转换为数组。
addNewChat = async (userId, matchedUserId) => {
const user1 = await getUserDataById(userId);
const user2 = await getUserDataById(matchedUserId);
console.log(JSON.stringify('User data: ' + user1));
return admin // don't forget to return the Promise!
.database()
.ref('/chats')
.push({
members: { [userId]: true, [matchedUserId]: true }, // FYI: these are "use value as the key" instructions not arrays.
[userId]: { username: user1.username },
[matchedUserId]: { username: user2.username },
});
};