Catching vs. not catching specific error types in dart - any difference in behavior? - dart

My understanding of catching errors was that if a certain error is 'caught', the code in a method following the catch block would not execute unless you have a finally statement afterwards.
However, if I catch a certain error type, but don't have a return or a throw/rethrow statement at the end, it does seem to keep going with the further code in the method.
I am catching a certain exception type, with the statement on CustomException catch (error) but I'm not planning to rethrow the error, and I don't need to do anything with the actual error. I don't have a return or a rethrow statement, as I assumed the catch block. I have two questions to make sure I'm understanding this behavior properly:
First question - if I don't plan to use the specific error inside my catch block, does adding catch (error) after on CustomException actually make a difference? It seems like it's ok to do it with or without it.
Second question - does my catch block need to have a return/throw/rethrow statement at the end in all cases to prevent the method from performing any further code?
Code example 1: With the catch (error) statement:
try {
...
} on CustomException catch (error) {
...
} catch (error) {
rethrow;
}
print('Is this method still running?');
Code example 2: without the catch (error) statement:
try {
...
} on CustomException {
...
} catch (error) {
rethrow;
}
print('Is this method still running?');

Your two examples aren't the same; one catches CustomException and the other catches PlatformException. Presuming that you meant them to be the same, then the difference between on CustomException and on CustomException catch (error) is that the second way allows you to do something with the thrown object (or if you use on CustomException catch (error, stacktrace), to do something with the stacktrace too).
The Dart Language Tour covers this:
Use on when you need to specify the exception type. Use catch when your exception handler needs the exception object.
Additionally, doing:
catch (error) {
rethrow;
}
is unnecessary noise. Just omit it and let the thrown exception go uncaught.

Related

withThrowingTaskGroup - No calls to throwing functions occur within 'try' expression

Problem:
I have the following function which shows a warning No calls to throwing functions occur within 'try' expression
Questions:
Why is this warning shown? (The code inside the task throws an error)
What should I do to propagate the error to the caller of f1?
Code:
func f1() async throws {
try await withThrowingTaskGroup(of: Int.self) { group in //No calls to throwing functions occur within 'try' expression
group.addTask(priority: .high) {
throw NSError()
}
}
}
You indeed have not called any throwing functions, or thrown anything, in the withThrowingTaskGroup closure. You've just added a task for the group to run. This by itself won't throw anything. addTask is not marked throws, though its closure parameter is. It will only throw when you wait for the task's completion in one way or another.
For example:
try await group.waitForAll()
Or if you want to loop through each task of the group:
for try await someInt in group {
// ...
}
If you return something in the withThrowingTaskGroup closure, that's what withThrowingTaskGroup will return too. If you throw an error in the closure, withThrowingTaskGroup will throw that error (since it is rethrows), and so will f1.

Why does this function return finaly?

Why does this function return finaly? Is not we catching the error?
String _test(){
try {
throw Exception('error');
} catch (e) {
return 'catch';
} finally {
return 'finaly';
}
}
Finally block is executed regardless of catching the error. It always executes when the try block exits.
EDIT:
https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break.
From this quote, it is evident that finally is usually used for cleaning up the code. That's why it is executed before the catch block, to avoid being bypassed by return

Dart future and rethrow

Is there any rethrow (not throw) equivalent for futures in dart?
myFunc()
.then(processValue)
.catchError(handleError);
Yes.
If the handleError of a catchError throws the same error object again (because it acts the same way as then's onError), it is considered a "rethrow" and it will also retain the original stack trace.
If you just want to catch some types of errors, and rethrow the rest, you can use the test parameter of catchError:
myFunc()
.then(processValue)
.catchError(handleError, test: (e) => e is MyException);
This only catches MyException exceptions and lets any other error pass through, with no need for you to rethrow them. The test can do any testing, not just type checks.
Also, if you use async functions, you can just use rethrow:
...) async {
try {
var processValue = await myFunc();
....
} catch (e) {
if (something(e)) {
whatnot();
} else {
rethrow;
}
}

Swift: catch error case with parameters but with access to the error object

I would like to catch a custom error with parameters, but also get access to the error to call some function on it. How do you do that? (I don't want to just catch the CustomError and have a switch inside the catch block.)
enum CustomError: Error {
case error(code: Int)
func describe() -> String {
...
}
}
...
do {
try bad()
} catch let error as CustomError.error(let code) { // This doesn't work
print(error.describe())
} catch {
....
}
A bit repetitive, but after reading through the language reference, I don't think there is a way to elegantly do this:
do {
try bad()
} catch CustomError.error(let code) {
print(CustomError.error(code: code).describe())
} catch {
}
This makes use of the fact that code and the case .error are the only 2 pieces of state that CustomError has. This means that we can recreate the error object, and call describe on that.

Catch an objectiveC exception that was thrown as a result of a javascript script

Is there any way of catching an Objective-C exception that was thrown as a result of a JavaScript script evaluation?
For example:
I have a class Obj with a method canThrow that I have exported through JSExport. From some script I call this method and it indeed throws an exception.
Any way I can handle it?
I have already tried to wrap the script evaluation code in a try-catch, but that didn't help.
Your question is a little bit unclear, but I will try to answer it anyway.
If you need to raise an exception from Objective-C to Javascript, you should use -[JSContext exception] property. See following question for details.
Passing exception from Javascript to Objective-C is straightforward, you simply export some method, that will handle exception in Objective-C like:
myJSContext[#"PassExceptionToObjC"] = ^void(JSValue *)jsException {
// Handle exception
}
And then use following code in Javascript:
try {
// some code
}
catch (exception) {
PassExceptionToObjC(exception);
}
Alternatively you can return specific value from your Javascript to Objective-C. Like:
function doSomething() {
try {
// Do something
return 'Ok';
}
catch (error) {
return 'Error happens ' + error.message;
}
}
In case you need to avoid throwing Objective-C exception in method, called from Javascript, you simply should add #try/#catch in your Objective-C method or block:
myJSContext[#"DoSomething"] = ^void(JSValue *)someValue {
#try {
// Do something
}
#catch (NSException *exception) {
// Handle exception
}
}
Or, preferred, change logic of Objective-C code, that trigger exception.
Similar way applies if you need to avoid exception in Javascript, called from Objective-C. You simply add try/catch. In most cases you may simply ignore exceptions in JavaScript, called from Objective-C. But I suggest to implement exception handing on Objective-C side for any non-trivial Javascript, at least to simplify troubleshooting.
Hope it helps.

Resources