I am using try catch inside try block to print relative message or get to know in which method error happened.
code snippet
for (const searchUrl of savedSearchUrls) {
console.log("here");
// function will get all the links of profiles in saved search url
try {
const links = await scrapeFromurl(browser, searchUrl);
try {
saveToDatabase(links);
} catch (e) {
handleError(e, "eror while saving to database");
}
} catch (err) {
handleError(err, "error in scrapeFromurl()");
}
}
I have searched on google but couldn't find related topic.
what are the other ways to acplish similar things? what are the best practice to handle this type of situation.
I am using try catch inside try block to print relative message or get to know in which method error happened.
code snippet
for (const searchUrl of savedSearchUrls) {
console.log("here");
// function will get all the links of profiles in saved search url
try {
const links = await scrapeFromurl(browser, searchUrl);
try {
saveToDatabase(links);
} catch (e) {
handleError(e, "eror while saving to database");
}
} catch (err) {
handleError(err, "error in scrapeFromurl()");
}
}
I have searched on google but couldn't find related topic.
what are the other ways to acplish similar things? what are the best practice to handle this type of situation.
Share Improve this question asked Aug 29, 2022 at 18:24 Kashif GhafoorKashif Ghafoor 4164 silver badges14 bronze badges 6- If all you are going to do is handle each exception the same way, you can actually just use the uncaughtexception handler in window. Try / catch an exception if you are going to handle it in a specific way – ControlAltDel Commented Aug 29, 2022 at 18:28
- I am using linux OS. Moreover, can you elaborate your point a little bit. I am beginner. – Kashif Ghafoor Commented Aug 29, 2022 at 18:30
- Yes it is good practice, you can throw a general error in main catch and specific errors for specific operation in inner catches. – linusw Commented Aug 29, 2022 at 18:36
-
Is
saveToDatabase
asynchronous as well? – Bergi Commented Aug 29, 2022 at 19:19 - 1 Have a look at stackoverflow./questions/44663864/… – Bergi Commented Aug 29, 2022 at 19:31
3 Answers
Reset to default 3By default a single try-catch block is enough without needs for nesting other try-catches into it. However, there may be some legitimate exceptions from these rules.
Exception 1: Different handlers for the same exception
Let's consider the following example
try {
myroutine(); // may throw three types of exceptions
} catch (e) {
if (e instanceof TypeError) {
// statements to handle TypeError exceptions
} else if (e instanceof RangeError) {
// statements to handle RangeError exceptions
} else if (e instanceof EvalError) {
// statements to handle EvalError exceptions
} else {
// statements to handle any unspecified exceptions
logMyErrors(e); // pass exception object to error handler
}
}
It is perfectly possible that inside your try
there is a section where a given error type, like a RangeError
needs a different way of handling than the main catch
. In this case it might make sense to have another try-catch inside your try, albeit, in this case, for better readability it would make sense to consider the inner try as a method and call that, so you would not physically nest the try-catch blocks, but separate the concerns of the try-catches into separate methods.
Exception 2: Handling a certain type of error only at a section of a try-block
It is quite possible that you want your try-catch to throw the error further in the majority of your try
block, but, in a specific section you want it to handle it. Again, in this case it would make sense to separate the inner try
into its own method.
Conclusion
Having nested try-catches are nonintuitive for a reader, therefore it makes sense to separate the inner try
into its own method whenever you encounter the need to nest tries. Yet, as the examples above show, there are legitimate needs to drift away from the outer handling of an error for some sections. However, by default it is a good idea to consider such sections as separate concerns worthy of separating from the method. Of course, sometimes you might want to keep nested try-catches without separating their concerns, but more often than not it is worth to apply the separations. So, a rule of thumb that you may want to consider is to refactor nested try-catches either into separate methods or a single try-catch, unless there is a very good reason not to do so.
I would suggest using only one try catch block and specific error instances for each method, then in catch block you can simply check which method throws an error by using instanceof
operator
class ScrapeError extends Error {
message = "error in scrapeFromurl()"
}
class DBError extends Error {
message = "eror while saving to database"
}
async function scrapeFromurl() {
throw new ScrapeError();
}
async function saveToDatabase(links) {
throw new DBError();
}
async function main() {
try {
const links = await scrapeFromurl();
await saveToDatabase(links);
} catch (e) {
if (e instanceof ScrapeError) {
console.log('scrape', e);
}
if (e instanceof DBError) {
console.log('dberror', e);
}
}
}
main();
In asyncronous scripts you can use domains for error handling. And trycatch in trycatch can be treated like domain in domain, which is pointless. Moreover, programmers always tend to prevent the code from growing horizontally like this
{
...
{
...
{
... (and so on)
{
}
}
}
}
So it is a really bad idea. I can keep on telling drawbacks of this approach, but not going to. Just use one trycatch with switchcase inside to handle all errors