Search code examples
javascriptasync-awaittry-catch

How to catch an error coming from another async function


I have a script which contains 2 async functions. The first one gets Geo Location data from a promisified navigator.geolocation.getCurrentPostition and then does reverse Geo Location using geocode.xyz. I have the whole function in a try/catch block which then does a console.log of the error, if one is generated. I am able to generate an error by modifying the url to one that cannot be resolved. So far, this is working fine.

The problem is when I am calling that async function from another async function. In the second function, I also have a try/catch block, the problem is, the catch never gets executed.

My goal is to create a TextNode with the error and append it to a div, instead of appending the Geo Location data to the div. Here is my JS code:

const options = {
  enableHighAccuracy: true,
};

const getPosition = () => {
  return new Promise((resovle, reject) => {
    navigator.geolocation.getCurrentPosition(resovle, reject, options);
  });
};

const getAddress = async () => {
  try {
    const pos = await getPosition();
    const { latitude: lat, longitude: lng } = pos.coords;
    const resGeo = await fetch(`https://ggeocode.xyz/${lat},${lng}?geoit=json`);
    console.log(`The resGeo response is ${resGeo}`);
    const dataGeo = await resGeo.json();
    const streetNumber = dataGeo.stnumber;
    const streetName = dataGeo.staddress;
    const suburb = dataGeo.city;
    const address = `${streetNumber} ${streetName}, ${suburb}`;
    return address;
  } catch (err) {
    console.log(`An error has occured: ${err.message}`);
  }
};

const populateData = async () => {
  try {
    showLoader();
    const address = await getAddress();
    const container = document.querySelector(".container");
    addressContent = document.createTextNode(`Your address is: ${address}`);
    container.appendChild(addressContent);
    hideLoader();
  } catch (err) {
    errorContent = document.createTextNode(
      `An error has occured: ${err.message}`
    );
    container.appendChild(errorContent);
  }
};

const showLoader = () => {
  const loader = document.querySelector("#loader");
  loader.classList.add("display");
};

const hideLoader = () => {
  const loader = document.querySelector("#loader");
  loader.classList.remove("display");
};

const button = document.querySelector("#button");

button.addEventListener("click", populateData);

Here are 2 code pens - fetch working and force error (wrong DNS name)


Solution

  • The problem is when I am calling that async function from another async function. In the second function, I also have a try/catch block, the problem is, the catch never gets executed.

    If you mean that the catch block in populateData never gets triggered by an error in getAddress, that's because you've explicitly handled the error with a try/catch in getAddress. This is no different than with synchronous functions: If you handle the error, it stops propagating up the call chain.

    Either:

    1. Don't handle the error (usually you don't want to handle errors anywhere but in the entry point functions — event handlers and such) so that it propagates

    2. If you need to handle it in getAddress, either re-throw it from the catch in getAddress or have getAddress return a failure value (null for instance).

    But your catch handler in getAddress just logs and suppresses the error, so #1 would be the way to go.