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?
2 Answers 2
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).
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);
Explore related questions
See similar questions with these tags.