【问题标题】:How to optimize this firebase real time database requests?如何优化这个 firebase 实时数据库请求?
【发布时间】:2021-05-16 13:34:56
【问题描述】:

我正在构建一个问答游戏。

用户成功完成一个关卡后,我调用服务器请求打开下一个关卡。 除了打开下一个关卡,我还调用了一个更新用户分数的服务器请求。

您对如何优化它有什么建议,以便花费更少的时间,也许可以取出一个服务器请求来更新两个字段?

我使用 Firebase,它在实时数据库中的外观如下:

这里有一些代码:

如果答案正确:

const onAnswerPressedHandler = async answer => {
    const rightAnswer = answer === selectedLevel.rightAnswer;
    dispatch(setShowLoader(true));
    if (rightAnswer) {
      if (isNotLastLevel) {
        await updateRank();
        await unlockNextLevelIfExist();
      } else if (isNotLastWorld) {
        await updateRank();
        await unlockNextWorldIfExist();
      } else {
        await updateRank();
        navigation.pop(3);
      }
    }

    dispatch(setShowLoader(false));
  };

在 Firebase 中更新排名:

export const updateUserScoreAndRank = (score, rank) => new Promise(async (resolve, reject) => {
  try {
    await database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_DETAILS)
      .child('score')
      .set(score);
    await database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_DETAILS)
      .child('rank')
      .set(rank);
    resolve();
  } catch (e) {
    reject(e);
    console.log(e);
  }
});

解锁下一关:

export const setLevelPassed = (worldIndex, levelIndex) => new Promise(async (resolve, reject) => {
  try {
    await database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_GAME_DETAILS)
      .child(firebaseRefs.CURRENT_USER_GAME_DATA)
      .child(worldIndex.toString())
      .child(firebaseRefs.GAME_QUESTIONS)
      .child(levelIndex.toString())
      .child(firebaseRefs.IS_LOCKED)
      .set(false);
    resolve();
  } catch (e) {
    reject(e);
    console.log('setLevelPassed', e);
  }
});

知道如何改进请求吗?

【问题讨论】:

  • 是的,你的建议对我很有帮助。

标签: javascript firebase react-native firebase-realtime-database


【解决方案1】:

您在这里使用了两个单独的 await 调用:

export const updateUserScoreAndRank = (score, rank) => new Promise(async (resolve, reject) => {
  try {
    await database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_DETAILS)
      .child('score')
      .set(score);
    await database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_DETAILS)
      .child('rank')
      .set(rank);
    resolve();
  } catch (e) {
    reject(e);
    console.log(e);
  }
});

这意味着调用是按顺序执行的,只有在两者都完成后,方法返回的 Promise 才会解析。

但是这两个调用不以任何方式相互依赖,因此您可以并行执行它们,这样第二个调用就不会等待第一个调用完成。这样做,您还可以尝试自定义承诺并从Promise.all() 返回:

export const updateUserScoreAndRank = (score, rank) => {
  return Promise.all([
    database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_DETAILS)
      .child('score')
      .set(score),
    database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_DETAILS)
      .child('rank')
      .set(rank);
  ]);
});

为了进一步简化,您可以使用单个多位置更新,而不是两个数据库调用。这不会再产生显着的性能差异,因为 Firebase 已经通过单个连接pipelines the requests,但它会使代码更短一些,并且更新是原子的。

export const updateUserScoreAndRank = (score, rank) => {
  return database()
      .ref(firebaseRefs.USERS_REF)
      .child(auth().currentUser.uid)
      .child(firebaseRefs.CURRENT_USER_DETAILS)
      .update({ rank, score })
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    • 1970-01-01
    相关资源
    最近更新 更多