1
\$\begingroup\$

This is a fairly simple bit of code:

async function fetchData() {
    console.log("fetching data");
    let json;
    try {
        const data = await fetch(endPoint);
        json = await data.json();    
    }
    catch (error) {
        console.error(error);
        handleError(error);
    }

    try {
        await saveData(json);
    } catch (error) {
        console.error(error);
        handleError(error);
    }
}

console.info("start running");
setInterval(fetchData, config.newsapi.polling_interval);
console.info("application is running"); 

What we're doing is - every 15 minutes or so, we're polling an API endpoint, and then saving the results into a database.

So there's two main kinds of errors we might get here:

  • The API I fetched the data from might return some kind of error - it might be down, or my API key might be wrong, or I've gone over the rate limit or whatever.
  • The database might return some kind of error. For all the same reasons, but a completely different service.

Now in terms of handling these errors, for now all I'll be doing is logging the error, and send me an email.

But I can imagine, that in the future, I might want to handle these two distinct kinds of errors differently. As such, I've created two different try catch blocks, that gives me the flexibility to handle them differently.

But it does look a bit messier, in my opinion. The other way I could write this is:

async function fetchData() {
    console.log("fetching data");
    try {
        const data = await fetch(endPoint);
        const json = await data.json(); 
        await saveData(json);   
    }
    catch (error) {
        console.error(error);
        handleError(error);
    }

}

console.info("start running");
setInterval(fetchData, config.newsapi.polling_interval);
console.info("application is running");

This looks so much tidier. But in which case - it seems like the error handling is a bit trickier.

I guess I could put a switch statement in the catch block handle different errors differently, but is that a bit messy? Any suggestions or guidelines for navigating this?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

In my opinion it is much better to place the saveData call inside the first try-catch block.

This avoids calling saveData with an undefined value in case an exception occurs in calls to fetch or data.json, and gives the json variable a clean scope.

Depending on the granularity needed for error handling I would prefer to surround

await saveData(json);

with try-catch if necessary. However, a switch statement could also be a natural approach if you have a clear distinction on the exceptions thrown (e.g. error numbers).

\$\endgroup\$
1
\$\begingroup\$

Promise.catch for errors

Why use an async function at all?

You are using an interval that ignores the promise returned by the async fetchData, so you are not interested in whether or not the get and post succeed, you just want to report errors as they happen.

Promises have a catch callback that is called when there is an error. Simply redirect the error passed to the catch to your handleError function.

That way you can handle the errors in the functions who's role is appropriate rather than have fetchData handle both the get or post errors

function postData(data) {
   const url = ????;
   const options = {
       method: "POST",
       body: JSON.stringify(data), 
       headers: {"Content-Type": "application/json"}
   };
   fetch(url, options).catch(handleError);
}

function getData() {
    fetch(endPoint)
        .then(data => { data.json().then(postData) }) //assumes JSON is reliably formated 
        .catch(handleError);      
}

setInterval(getData, config.newsapi.polling_interval);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.