Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Promise.race not resolving in useEffect function for React Native mobile app

I am setting up a progressive Image loader (download and replacing an image with the same image in increasing quality). First I am making a cache check to see if the image is already cached. However, while this loads, I am downloading lower quality images in case there is no cache hit of the image I want to load. The code looks like this:

useEffect(() => {
  // checks if image exists in cache, sets it to imageSource if it does
  async function checkCache(); 

  // downloads 2 lower quality images and sets them to imageSource when their download finishes
  async function downloadAndSetSmallAndMediumImages(); 

  // downloads the highest quality image and stores it in cache
  async function handleFinalBigImageDownloadAndSet();

  async function handleRace() {
    const raceResult = await Promise.race([checkCache(), downloadAndSetSmallAndMediumImages()]);
    console.log('here', raceResult);
    if (isCacheChecked && !cacheHit) {
      console.log('cache miss');
      await downloadAndSetSmallAndMediumImages();
      await handleFinalBigImageDownloadAndSet();
    else {
      console.log('cache hit');
    }
  }

  handleRace();
  return () => {};
}, [imageSource]);

In the handleRace() function, the console log never appears – it seems then that the Promise.race() is not resolving. I have set up some console.log() at the end of the checkCache() function, and these are actually logged in the console. The next line executing should then be the Promise.race() resolving and the subsequent logging of the result. Thus, on the UI of the app, the loading indicator stays indefinitely (since imageSource needs to be set by these functions) until I refresh the page and then suddenly the images are visible, yet the console.log() after the Promise.race() still does not show.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You need to work with the react lifecycle.

The react useEffect do not handle async callbacks, so you should use promises without the await, just using the .then and the useSetate, for example:

// outside the component context if it's possible
async function checkCache(); 

async function downloadAndSetSmallAndMediumImages(); 
...
  const [raceResult, setRaceResult] = useState(false):
  useEffect(() => {
  
    Promise.race([checkCache(), downloadAndSetSmallAndMediumImages()]).then(setRaceResult);

  }, [imageSource])

  useEffect(() => {
    console.log('here', raceResult);
    if (isCacheChecked && !cacheHit) {
      console.log('cache miss');
      // Use fire and forget if it's possible and apply the same approach with the useState in case of require to handle an action once the promise finish
      downloadAndSetSmallAndMediumImages().then(() => handleFinalBigImageDownloadAndSet());
    else {
      console.log('cache hit');
    }
  }, [raceResult, isCacheChecked, cacheHit])
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading