简体   繁体   中英

Does async function try catch block can wrap a called async function that also may throw an error?

I have the following code:

const getJSON = async function(url, errorMsg = 'Something went wrong') {
  return fetch(url).then(response => {
    if (!response.ok) throw new Error(`${errorMsg} (${response.status})`);

    return response.json();
  });
};

const outerFunc = async function() {
  try {
    let x = await getJSON();
  } catch (err) {
    console.log(err);
  }
}

outerFunc();

I tried to run the code inside the console and get an error:

VM60:2 Fetch API cannot load chrome://new-tab-page/undefined. URL scheme "chrome" is not supported.

I want to understand if the try/catch block that surrounds the **outerFunc ** function can catch an error that will come from the called async function ( asyncFunction ), or asyncFunction should handle its error by himself. I know that in Java it's ok to "propagate" the error. What is the correct behavior in JS?

Generally, you want to catch errors at a point where you can do something useful in response to the error. Often, this is not the point where the API is called, but somewhere further up the call stack. Allowing errors to naturally propagate upwards to where they can be handled reasonably is a fine idea.

For example, in a real application, if there's a catch block which is composed solely of a console.log , that's often (not always) an indication that the error should be caught somewhere else. When there's an error, one will often want to inform the user that there was a problem, so the following sort of pattern is very common:

getAPI()
  .then(populateWithResults)
  .catch((error) => {
    const div = document.querySelector('.errors').appendChild(document.createElement('div'));
    div.textContent = 'There was an unexpected error: ' + error.message;
  });

where getAPI does no catching of its own, but simply allows the caller to handle possible errors - similar to what your getJSON function is doing.

Usually you'll only want one point where an error is caught, but occasionally you might want to catch it in multiple places - for example, perhaps a sub-component wants to do something in particular when an error is encountered, but it also wants to notify the callers that there's a problem. In such cases, re-throwing the error could look like:

const makeSubComponent = () => {
  const componentContainer = document.querySelector('.container');
  const populateSubComponent = () => {
    // ...
  };
  return getAPI()
    .then(populateSubComponent)
    .catch((error) => {
      componentContainer.textContent = 'Something went wrong...'
      throw error; // Inform the caller of makeSubComponent of the error
    });
};

allowing both makeSubComponent and its caller to deal with possible problems.

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