0

I know this has been asked a gazillion times. I've asked it myself. Specifically to the code below I don't know why this doesn't resolve.

const householdPics = (data, props) => {
  let refImg;

  async function refDetails() {
    let urlResult;
    const ref = await props.firebase.storageRef(`images/${data.profilePic}`);
    return urlResult = new Promise((resolve, reject) => {
      ref.getDownloadURL()
      .then(url => resolve(url))
      .catch(e => reject(e))
    })
  }

  if (!data.profilePic || data.profilePic == 'NULL') {
    refImg = require("../../assets/img/empty-avatar.png");
  } else {
    refImg = refDetails();
  }

I'm sure I'm over complicating this, I've been at it so long I'm all confused myself. I would expect refImg = refDetails(); to resolve to a url. if I console.log urlResult I get an img url from firebase. However when I use refImg in another block of code:

src appears as Object Promise

I also tried:

  async function refDetails() {
    const ref = await props.firebase.storageRef(`images/${data.profilePic}`);
    const refUrl = await ref.getDownloadURL();
    return refUrl;
  }

Here is another attempt I've tried after reading up more on this. Still failing :(

  let refImg;

  function refDetails() {
    const ref = props.firebase.storageRef(`images/${data.profilePic}`);
    const imgUrl = ref.getDownloadURL()
    return imgUrl.then(url => {return url})
  }

  if (!data.profilePic || data.profilePic == 'NULL') {
    refImg = require("../../assets/img/empty-avatar.png");
  } else {
    const resultImg = refDetails();;
    refImg = resultImg;
  }

How can I pass the return value of ref.getDownloadURL() to refImg?

FabricioG
  • 3,107
  • 6
  • 35
  • 74
  • 1
    `async` functions will always return a promise – Nick Parsons Jan 29 '20 at 02:07
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! And yes, you can't make `refImg` being anything else but a promise – Bergi Jan 29 '20 at 02:11
  • I updated another example that still gives me the same thing. @Bergi – FabricioG Jan 29 '20 at 07:35

1 Answers1

0

Try:

const householdPics = async (data, props) => {
  let refImg;

  async function refDetails() {
    let urlResult;
    const ref = await props.firebase.storageRef(`images/${data.profilePic}`);
    return await ref.getDownloadURL():
  }

  if (!data.profilePic || data.profilePic == 'NULL') {
    refImg = require("../../assets/img/empty-avatar.png");
  } else {
    refImg = await refDetails();
  }

UPDATE:

ref.getDownloadURL() is a Promise and in order to use the result value, which is the url, you MUST get it inside the callback of .then, or you use async await syntax, which make async process seems to be synchronize like my previous answer did.

imgUrl.then(url => {return url}) Promise.then() is also a Promise so you're still returning promise in the function in your second attempt. Therefore refImg = resultImg results in making refImg an "Promise returning a url".

The reason you think the previous answer doesn't work is probably that, you called householdPics() and try to get the value without using .then or await. Since I made householdPics an async function, it will always returns a Promise. So again, you have to get the value with .then or await.

UPDATE 2

I just tried about returning a Promise in async function. It seems that if you return a Promise instead of resolved value in an async function like:

async function refDetails() {
    let urlResult;
    const ref = await props.firebase.storageRef(`images/${data.profilePic}`);
    return ref.getDownloadURL():
  }

then await the function:

refImg = await refDetails();

it still resolves and returns the value of the Promise. So you can save a that await in the async function if you're returning it (while I don't recommend it since it's quiet confusing).

Hao-Cher Hong
  • 230
  • 2
  • 6
  • still appears as an object promsie – FabricioG Jan 29 '20 at 02:45
  • Are you sure you've added await on both before ref.getDownloadUrl and refDetails at the last line? – Hao-Cher Hong Jan 29 '20 at 02:48
  • Yes I'm sure. I didn't downvote by the way. @Hao-Cher Hong – FabricioG Jan 29 '20 at 06:59
  • No problem. That's weird. Could you describe how do you "use refImg in another block of code"? – Hao-Cher Hong Jan 29 '20 at 07:27
  • Yes but that's not what's causing the problem. I just posted another attempt in the question with out async await. @Hao-Cher Hong – FabricioG Jan 29 '20 at 07:33
  • I've updated my answer and I think you should check https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function to understand more about Promise and async function. – Hao-Cher Hong Jan 29 '20 at 07:54