I encountered a problem in VS Code with Custom Exception Handling - flutter

I keep getting the following error message in VS Code when I try to run this dart package:
**The method 'errorMessage' isn't defined for the type 'Object'.
Try correcting the name to the name of an existing method, or defining a method named 'errorMessage'.
**
Anytime I write this code:
void main(){
try {
depositMoney(-200);
} catch (e) {
print(e.errorMessage());
}
}
class DepositException implements Exception {
String errorMessage() {
print("You cannot enter amount less than 0! ");
return errorMessage();
}
}
void depositMoney(int amount) {
if (amount < 0) {
throw new DepositException();
}
}
What should I do??

Change your try catch block like this,
try {
depositMoney(-200);
} on DepositException catch (e) {
print(e.errorMessage());
}
This is because, DepositException is a custom exception class.
If you want catch all errors, you can do it this way,
try {
depositMoney(-200);
} catch (e) {
if(e is DepositException){
print(e.errorMessage());
}else{
print(e);
}
}

Related

flutter dart Try/Catch not working properly

While learning flutter/dart, I came across this issue:
I'm calling this method in a FutureBuilder somewhere in my app:
Future<DatabaseUser> getOrCreateUser({required String email}) async {
try {
final user = await getUser(email: email);
return user;
} on UserDoesNotExistsException {
final createdUser = await createUser(email: email);
return createdUser;
} catch (e) {
print(e);
rethrow;
}
}
Once called for the first time, the "getUser" throws a UserDoesNotExistsException, which is correct, so it should go to the line:
} on UserDoesNotExistsException {
This is the issue, it always goes straight to the line:
} catch (e) {
If I print (e), I have UserDoesNotExistsException (see screenshot)
Let me know if you need more context here, what could make sense in that situation? Why is the Exception not caught by the right bloc?
Any help would be really appreciated
PS: I'm following this 37h+ video tutorial: https://www.youtube.com/watch?v=VPvVD8t02U8&t=28781s I'm at 21:36:00
Thanks
Screenshot Debugger
Issue solved.
As julemand101 suggested, a print(e.runtimeType) exposed the type of e as Type and not Exception.
The reason was a missing () when the Exception is thrown:
if (result.isEmpty) {
throw UserDoesNotExistsException;
} else {
return DatabaseUser.fromRow(result.first);
}
instead of
if (result.isEmpty) {
throw UserDoesNotExistsException();
} else {
return DatabaseUser.fromRow(result.first);
}
Visual Studio Code doesn't give any warning about this by default, but as julemand101 suggested in the comments, the analyzer can be configured to give a warning when you don't throw an Error or Exception:
https://dart-lang.github.io/linter/lints/only_throw_errors.html

How to catch exception in a callback function in Dart (Flutter)?

I'm using WebSocket variable in my MyWebSocket class. For listen i give a callback function as parameter.
If this callback function throws an exception in calling class MyChat, then i can not catch that exception anywhere.
My simplified code is:
class MyWebSocket {
WebSocket _ws;
...
// initialized in controller: _ws = WebSocket.connect(_some_url_);
// everything works (connect, listen)
...
void listen({void Function(dynamic) myOnListen}) {
try {
_ws.listen(myOnListen)
.onError((e) => print("MyWebSocket in MyChat.onError: $e"));
} catch (e) {
print("Catched in MyWebSocket: $e");
}
}
}
class MyChat {
MyWebSocket _chatWs = MyWebSocket();
...
void initWS() {
try {
_chatWs.listen(myOnListen: processMsg);
} catch (e) {
print("Catched in MyChat: $e");
}
}
void processMsg(dynamic msg) {
if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
throw Exception("There is my Exception");
}
}
I have built try-catch in every possible place to catch exceptions - no success, i got only unhandled exception:
E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Exception: There is my Exception
E/flutter: #0 MyChat.processMsg
Beware that you cannot use the passed listener as a key for later removal. For that you can pass the new listener created in MyWebSocket class when listen() is called, then use this key to remove the listener.
class MyWebSocket {
WebSocket _ws;
void listen({void Function(dynamic) myOnListen, void Function(Error) onError}) {
try {
_ws.listen((){
try {
myOnListen({"label": "DATA"});
} catch (e) {
if(onError is Function)
onError(e)
}
})
.onError(onError);
} catch (e) {
print("Catched in MyWebSocket: $e");
}
}
}
class MyChat {
MyWebSocket _chatWs = MyWebSocket();
void initWS() {
try {
_chatWs.listen(myOnListen: processMsg, onError: (Error error){
print("ERROR: "+error.toString());
});
} catch (e) {
print("Catched in MyChat: $e");
}
}
void processMsg(dynamic msg) {
if(_some_stuff_like_invalid_msg_or_not_logged_in_...)
throw Exception("There is my Exception");
}
}
You need to handle it inside your processMsg
If you analyze carefully the execution of your code the _ws.listent register a listener for when you receive a message and that will happen in the FUTURE, but you don't get an error WHILE you are REGISTERING your listener that's why that doesn't work the way you expect.
processMsg will do something in the future, it will throw an error and it's at the end of the pipeline.
You are simulating an exception and nothing is handling it, it happens in a different stack frame, in the future.
The void listen({void Function(dynamic) myOnListen}) function execution is long gone when you receive and you precessMsg.
Alternatively you could do:
Function tryCatchHOF(Function cb) {
decorated(dynamic param) {
try {
cb(param);
} catch (e) {
print("$e");
}
}
;
return decorated;
}
void processMsg(dynamic msg) {
if (true) throw Exception("There is my Exception");
}
var processMsgWithTryCatch = tryCatchHOF(processMsg);
processMsgWithTryCatch('');
and then pass processMsgWithTryCatch down to your listener if you don't want to handle inside processMsg
I hope that make sense

Does RxJava2 Need Try/Catch on Create() Emitter?

Is this code:
Completable.create(emitter -> {
myDao().insert(data); // can throw exceptions
emitter.onComplete();
});
The same as this code:
Completable.create(emitter -> {
try {
myDao().insert(data); // can throw exceptions
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
});
In other words: Do I have to surround my code with try/catch in order to propagate errors or will it be done automatically for me?

How can I throw an exception within ListeningExecutorService?

I used ListeningExecutorService of guava in my project, got confused about the exception handling.
I used a thread pool, submit a task to it, and set a timeout to the listenableFuture, and add a callback to it.
final ListeningExecutorService threadPool = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
Futures.addCallback(listenableFuture, new FutureCallback<**>() {
#Override
public void onSuccess(#Nullable ** data) {
xxxxxxx;
}
public void onFailure(Throwable t) {
xxxxxxxxxx;
if (t instanceof CancellationException) {
throw new QueryException("yyyy");
} else {
throw new QueryException("zzzzz");
}
}
});
I can't catch the exception inside the callback. So I use another ListenableFuture to get the exception
ListenableFuture allFutures = Futures.allAsList(allFuturesList);
try {
allFutures.get();
} catch (CancellationException ce) {
throw new QueryException("");
} catch (InterruptedException t) {
throw new QueryException("");
} catch (ExecutionException e) {
Throwable t = e.getCause();
if (t instanceof QueryException)
throw (QueryException) t;
else
throw new QueryException();
} catch (QueryException qe) {
throw qe;
} catch (Exception e) {
throw new QueryException();
} finally {
}
But I when the callback throw a QueryException, the allFutures can't catch it, allFutures can only catch a CancellationException without the detail error message.
How can I get my detail error message?
Futures.allAsList doesn't do what you expect it to do
From the Javadoc: (emphasis is from me)
Canceling this future will attempt to cancel all the component futures, and if any of the provided futures fails or is canceled, this one is, too.
What you should probably do is create your own aggregating future. You can base your code on Guava's own internal mechanism. See the source code for more info.
Anyways, do not throw exceptions in your FutureCallback::onFailure method.

Returning empty IQueryable<>

I have this method that tries to get a list of things:
private static IQueryable<Thing> GetThings(int thingsType)
{
try
{
return from thing in entities.thing.Include("thingStuff")
select thing;
}
catch (Exception exception)
{
return new EnumerableQuery<Thing>(?????);
}
}
}
I want to return an empty IQueryable if I can't for whatever reason get the query to run. I don't want to return NULL because that could break the calling code. Is it possible or am I going totally wrong about this?
These answers are good and do work, however I have always felt using Empty and not creating a new List is cleaner:
Enumerable.Empty<Thing>().AsQueryable();
Try the following:
private static IQueryable<Thing> GetThings(int thingsType)
{
IQueryable<Thing> things = new List<Thing>().AsQueryable();
try
{
things = from thing in entities.thing.Include("thingStuff")
select thing;
return things;
}
catch (Exception exception)
{
return things;
}
}
I would add block finally {} and put my return type in that code.
This will take care of the issue by returning the type that your application expects.
private static IQueryable<T> GetThings(int thingsType)
{
IQueryable<T> list = new List<Thing>().AsQueryable();
try
{
list = from thing in entities.thing.Include("thingStuff")
select t;
}
catch (Exception exception)
{
// handle exception here;
}
finally {
return list;
}
}
}
Returning empty IQueryable<>
DbSet.Take(0)
I think this would be tidier:
private static IQueryable<T> GetThings(int thingsType)
{
try
{
return from thing in entities.thing.Include("thingStuff")
select t;
}
catch (Exception exception)
{
// Exception handling code goes here
return new List<Thing>().AsQueryable();
}
}