Renaud is Not Bill Gates
Renaud is Not Bill Gates

Reputation: 2074

using async/await with firebase

I'm trying to use async/await to get images from firebase storage, and this is my function:

import { ref as sRef, getDownloadURL } from "firebase/storage";
...    
async getCharacterIconUrl(character) {
  return await getDownloadURL(sRef(storage, `characters/${character}/icon`));
}

And then, I use this function here:

import { ref, child, get } from "firebase/database";
...
async componentDidMount() {
  const dbRef = ref(db);

  let snapshot = await get(child(dbRef, "en/characters"));
  if (snapshot.exists()) {
    let characters = Object.keys(snapshot.val()).map((key) => {
      return {
        _id: key,
        img: this.getCharacterIconUrl(key),
        ...snapshot.val()[key],
      };
    });
    this.setState({ characters: characters });
  } else {
    console.log("No data available");
  }
}

The problem I have is that img inside characters is never resolved.

How can I solve this?

Upvotes: 0

Views: 719

Answers (2)

Bao Huynh
Bao Huynh

Reputation: 1054

Since getCharacterIconUrl is an async function, it returns a promise. Therefore, your img field is a promise; combined with map(), that becomes like an array of promise. Therefore, we can use Promise.all() to resolve them

async componentDidMount() {
  const dbRef = ref(db);

  let snapshot = await get(child(dbRef, "en/characters"));
  if (snapshot.exists()) {
    let characterPromises = Object.keys(snapshot.val()).map(async (key) => {
      return {
        _id: key,
        img: await this.getCharacterIconUrl(key),
        ...snapshot.val()[key],
      };
    });
    this.setState({ characters: await Promise.all(characterPromises)});
  } else {
    console.log("No data available");
  }
}

Upvotes: 1

Phil
Phil

Reputation: 164729

Your getCharacterIconUrl function is async so you need to await it.

Try this...

const characters = await Promise.all(
  Object.entries(snapshot.val()).map(async ([_id, val]) => ({
    _id,
    img: await this.getCharacterIconUrl(_id),
    ...val,
  }))
)
this.setState({ characters });

Note that the .map() callback is also async. I'm also using Object.entries() since you want both keys and values.

Upvotes: 1

Related Questions