将 firebase 引用传递给函数,并获得 return 值
Pass firebase reference to function, and get return value
我正在尝试创建一个函数来检查移动的子弹是否击中了玩家。
代码简化 - shoot()
移动子弹,check_if_bullet_hit_player(bulletRef)
获取子弹参考,并检查子弹是否击中任何玩家。
这是我的代码:
function shoot(){
// ... moving bullet code
const bulletRef = firebase.database().ref(`bullets/${bulletKey}`);
if(check_if_bullet_hit_player(bulletRef)){
alert("player got hit");
bulletRef.remove();
}
}
function check_if_bullet_hit_player(bulletRef){
bulletRef.once("value").then(function(snapshot) {
//for simplicity I just return true - player got hit
return true;
}
}
代码未触发 alert()
。看完我觉得是异步的问题,但是我怎么给函数传递参数,然后得到函数的return值。
编辑:
这是完整的 check_if_bullet_hit_player()
函数,我循环遍历玩家,并检查子弹是否 <0.5
到达玩家(如果是 - 它算作命中):
function check_if_bullet_hit_player(bulletRef){
//bulletRef.once("value").then(function(snapshot) {
return bulletRef.get().then(snapshot => {
let bulletX = snapshot.val().x;
let bulletY = snapshot.val().y;
let shooterId = snapshot.val().shooterId;
//loop over players
const allPlayersRef = firebase.database().ref(`players`);
allPlayersRef.once("value", (snapshot) => {
players = snapshot.val() || {};
Object.keys(players).forEach((key) => {
if(getDistance(players[key].x, players[key].y, bulletX, bulletY) < 0.5){
if(players[key].id != shooterId){ //not the shooter
return true;
}
// ...
确实问题出在 once()
方法是异步的。但是你也忘了在check_if_bullet_hit_player()
函数中returnpromises chain
以下内容,如您在问题中所做的那样使用 then()
,应该可以解决问题:
function shoot() {
// ... moving bullet code
const bulletRef = firebase.database().ref(`bullets/${bulletKey}`);
check_if_bullet_hit_player(bulletRef)
.then(result => {
if (result)
bulletRef.remove();
})
}
function check_if_bullet_hit_player(bulletRef) {
return bulletRef.get().then(snapshot => { // See return at the beginning, and also that we use get()
return snapshot.exists(); // I think you should check if the snapshot exists
});
}
请注意,shoot()
函数也是异步的。所以如果你将它与其他函数调用链接起来,你需要使用 then()
(和 return 承诺链)或 async/await
.
根据您的评论和问题更新进行编辑:
同样,您没有 return 承诺链。您可以按如下方式修改它,但我建议您使用 every()
方法,该方法“为数组 中存在的每个元素执行一次提供的回调函数,直到它找到回调 return 是一个虚假值 "
function check_if_bullet_hit_player(bulletRef) {
let bulletX;
let bulletY;
let shooterId;
return bulletRef.get().then(snapshot => {
bulletX = snapshot.val().x;
bulletY = snapshot.val().y;
shooterId = snapshot.val().shooterId;
//loop over players
const allPlayersRef = firebase.database().ref(`players`);
return allPlayersRef.get(); // HERE we chain the promise
})
.then(allPlayersSnap => {
players = allPlayersSnap.val() || {};
let result = false;
Object.keys(players).forEach((key) => {
if (getDistance(players[key].x, players[key].y, bulletX, bulletY) < 0.5 && players[key].id != shooterId) {
result = true;
}
});
return result;
});
}
补充说明
好像这些函数是在前端执行的(你用的是firebase.database()...
)你应该在back-end里做计算,比如通过 Cloud Function,避免恶意用户伪造结果的可能性。
我正在尝试创建一个函数来检查移动的子弹是否击中了玩家。
代码简化 - shoot()
移动子弹,check_if_bullet_hit_player(bulletRef)
获取子弹参考,并检查子弹是否击中任何玩家。
这是我的代码:
function shoot(){
// ... moving bullet code
const bulletRef = firebase.database().ref(`bullets/${bulletKey}`);
if(check_if_bullet_hit_player(bulletRef)){
alert("player got hit");
bulletRef.remove();
}
}
function check_if_bullet_hit_player(bulletRef){
bulletRef.once("value").then(function(snapshot) {
//for simplicity I just return true - player got hit
return true;
}
}
代码未触发 alert()
。看完
编辑:
这是完整的 check_if_bullet_hit_player()
函数,我循环遍历玩家,并检查子弹是否 <0.5
到达玩家(如果是 - 它算作命中):
function check_if_bullet_hit_player(bulletRef){
//bulletRef.once("value").then(function(snapshot) {
return bulletRef.get().then(snapshot => {
let bulletX = snapshot.val().x;
let bulletY = snapshot.val().y;
let shooterId = snapshot.val().shooterId;
//loop over players
const allPlayersRef = firebase.database().ref(`players`);
allPlayersRef.once("value", (snapshot) => {
players = snapshot.val() || {};
Object.keys(players).forEach((key) => {
if(getDistance(players[key].x, players[key].y, bulletX, bulletY) < 0.5){
if(players[key].id != shooterId){ //not the shooter
return true;
}
// ...
确实问题出在 once()
方法是异步的。但是你也忘了在check_if_bullet_hit_player()
函数中returnpromises chain
以下内容,如您在问题中所做的那样使用 then()
,应该可以解决问题:
function shoot() {
// ... moving bullet code
const bulletRef = firebase.database().ref(`bullets/${bulletKey}`);
check_if_bullet_hit_player(bulletRef)
.then(result => {
if (result)
bulletRef.remove();
})
}
function check_if_bullet_hit_player(bulletRef) {
return bulletRef.get().then(snapshot => { // See return at the beginning, and also that we use get()
return snapshot.exists(); // I think you should check if the snapshot exists
});
}
请注意,shoot()
函数也是异步的。所以如果你将它与其他函数调用链接起来,你需要使用 then()
(和 return 承诺链)或 async/await
.
根据您的评论和问题更新进行编辑:
同样,您没有 return 承诺链。您可以按如下方式修改它,但我建议您使用 every()
方法,该方法“为数组 中存在的每个元素执行一次提供的回调函数,直到它找到回调 return 是一个虚假值 "
function check_if_bullet_hit_player(bulletRef) {
let bulletX;
let bulletY;
let shooterId;
return bulletRef.get().then(snapshot => {
bulletX = snapshot.val().x;
bulletY = snapshot.val().y;
shooterId = snapshot.val().shooterId;
//loop over players
const allPlayersRef = firebase.database().ref(`players`);
return allPlayersRef.get(); // HERE we chain the promise
})
.then(allPlayersSnap => {
players = allPlayersSnap.val() || {};
let result = false;
Object.keys(players).forEach((key) => {
if (getDistance(players[key].x, players[key].y, bulletX, bulletY) < 0.5 && players[key].id != shooterId) {
result = true;
}
});
return result;
});
}
补充说明
好像这些函数是在前端执行的(你用的是firebase.database()...
)你应该在back-end里做计算,比如通过 Cloud Function,避免恶意用户伪造结果的可能性。