简体   繁体   中英

How to optimize this firebase real time database requests?

I'm building a trivia game.

After the user successfully completes a Level, I calling a server request that opens the next Level. In addition to opening the next Level, I calling one more server request that updates the user's score.

Do you have a recommendation on how to optimize it, so that it takes less time, maybe take out one server request that will update the two fields?

I use Firebase and this how it looks inside realtime database:

在此处输入图像描述

Here some code:

If the answer is correct:

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));
  };

Updating rank in 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);
  }
});

Unlocking next Level:

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);
  }
});

Any idea how to improve the requests?

You're using two separate await calls here:

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);
  }
});

This means the calls are executed sequentially, and only once both are done does the promise returned by the method resolve.

But the two calls don't depend on each other in any way, so you can execute them in parallel so that the second one isn't waiting for the first one to be finished. Doing this, you can also get try of the custom promise and return the one from 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);
  ]);
});

For another simplification you can use a single multi-location update, instead of two database calls. This won't make a significant performance difference anymore, since Firebase already pipelines the requests over a single connection, but it will make the code a bit shorter, and the updates atomic.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM