I want to handle the exception from the 'onData' function(the first positional parameter), but the onError is not fired when the exception is thrown. I just got an 'Unhandled Exception' warning.
Am I misunderstanding the 'onError' on usage? When will it be fired?
The codes:
final Logger log = Logger('test logger');
client.getUrl(Uri.parse(url)).then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) {
try {
response.listen((d) {
throw Exception("TEST EXCEPTION");
}, onDone: () {
log.finer("onDone");
}, onError: (e, stack) {
log.warning("onError");
}, cancelOnError: true);
} catch (e, stack) {
log.warning("listen");
}
}).catchError((e, stack) {
log.warning("future");
});
Related
I am trying to implement a function that waits until a certain console event is sent.
E.g. there are several console.endTime calls being done (for performance debugging) and I want to wait until the last one (identified by a specific message text ) is done.
My code kind of works but the problem is that page.on adds new event listeners each time I call my waitForEvent function. I understand why that happens, but haven't found a solution that avoids this.
Code looks like this :
function waitForEndEvent() {
return new Promise((res, rej) => {
registerConsoleEvent(page, res, rej);
});
}
function filterMessage() {
return (msg) => {
try {
if (msg.type() == 'timeEnd') {
if (msg.text().includes("final time")) {
console.log('timeEnd:', msg.text());
res();
}
}
} catch (e) {
rej(e);
}
};
}
function registerConsoleEvent(page, res, rej) {
page.on('console', filterMessage(res,rej));
}
Any hint how I could solve this issue?
You can just remove the event listener after receiving the message. You can use the page.removeListener(...) method to remove the event listener. So the code would be like this
function waitForEndEvent() {
return new Promise((res, rej) => {
registerConsoleEvent(page, res, rej);
});
}
function registerConsoleEvent(page, res, rej) {
page.on('console', function consoleListener(msg) {
try {
if (msg.type() == 'timeEnd') {
if (msg.text().includes('final time')) {
console.log('timeEnd:', msg.text());
page.removeListener('console', consoleListener);
res();
}
}
} catch (e) {
rej(e);
}
});
}
Im coming from a Java background where I use the throws keyword to lead an exception to the method calling another method. How can I do that I dart?
Method called:
void _updateCurrentUserEmail() async {
await FirebaseAuth.instance
.currentUser()
.then((FirebaseUser user) {
_email = user.email;
});
}
How it is called:
try {
_updateCurrentUserEmail();
} on Exception {
return errorScreen("No User Signed In!", barActions);
}
But it seems like the Exception is not caught, because I still get a NoSuchMethodException and the errorScreen is not shown.
While you correctly used try/catch, the exception is coming from an async function that you did not await.
try/catch only catch exceptions thrown within that block. But since you wrote:
try {
doSomethingAsyncThatWillTrowLater();
} catch (e) {
}
Then the exception thrown by the async method is thrown outside of the body of try (as try finished before the async function did), and therefore not caught.
Your solution is to either use await:
try {
await doSomethingAsyncThatWillTrowLater();
} catch (e) {
}
Or use Future.catchError/Future.then:
doSomethingAsyncThatWillTrowLater().catchError((error) {
print('Error: $error');
});
From the docs,
If the catch clause does not specify a type, that clause can handle any type of thrown object:
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e'); <------------------
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
Change it to this:
try {
_updateCurrentUserEmail();
} on Exception catch(e){
print('error caught: $e')
}
Another way to handle error is to do the following:
void _updateCurrentUserEmail() async {
await FirebaseAuth.instance
.currentUser()
.then((FirebaseUser user) {
_email = user.email;
throw("some arbitrary error");
});
.catchError(handleError);
}
handleError(e) {
print('Error: ${e.toString()}');
}
If currentUser()’s Future completes with a value, then()’s callback fires. If code within then()’s callback throws (as it does in the example above), then()’s Future completes with an error. That error is handled by catchError().
Check the docs:
https://dart.dev/guides/libraries/futures-error-handling
Throw
Here’s an example of throwing, or raising, an exception:
throw FormatException('Expected at least 1 section');
You can also throw arbitrary objects:
throw 'Out of llamas!';
throwing an exception is an expression, you can throw exceptions in => statements, as well as anywhere else that allows expressions:
void someMethod(Point other) => throw UnimplementedError();
here is example
main() {
try {
test_age(-2);
}
catch(e) {
print('Age cannot be negative');
}
}
void test_age(int age) {
if(age<0) {
throw new FormatException();
}
}
hope it helps..
I would like to create an async method with Task that creates a file and immediately proceeds to executing next task which uploads created file to cloud.
Here is how this method looks:
public async TaskCreateAndUploadAsync()
{
await Task.Run(() =>
{
try
{
var _writeFile = new WriteFile(...);
_writeFile.DoWork();
}
catch (Exception e)
{
//Log..
}
}).ContinueWith((result) =>
{
if (!result.IsFaulted)
{
try
{
storage.UploadCreatedObject(...);
}
catch (Exception e)
{
//Log..
}
}
});
}
My question is: Is the way how I catch exceptions in each Task individually correct or I should use one try-catch block around whole "Task..Task.ContinueWith"?
Where to catch exceptions when using Task.ContinueWith?
The proper answer is "don't use ContinueWith". For asynchronous code, you can use await instead; for synchronous code like this, you can just use nothing:
public async TaskCreateAndUploadAsync()
{
await Task.Run(async () =>
{
try
{
var _writeFile = new WriteFile(...);
_writeFile.DoWork();
storage.UploadCreatedObject(...);
}
catch (Exception e)
{
//Log..
}
});
}
However, wrapping a method body in Task.Run like this is an antipattern; it's better to keep the method synchronous and have callers use Task.Run:
public void TaskCreateAndUpload()
{
try
{
var _writeFile = new WriteFile(...);
_writeFile.DoWork();
storage.UploadCreatedObject(...);
}
catch (Exception e)
{
//Log..
}
}
From your method names, it sounds like some of them should be asynchronous. I/O is inherently asynchronous. So, if you have truly asynchronous I/O (i.e., not using Task.Run for fake-asynchrony), then your resulting method may look like this:
public async Task TaskCreateAndUploadAsync()
{
try
{
var _writeFile = new WriteFile(...);
await _writeFile.DoWorkAsync();
await storage.UploadCreatedObjectAsync(...);
}
catch (Exception e)
{
//Log..
}
}
Note the use of await instead of ContiueWith in this last example.
I recently stumbled across the following Dart code:
void doSomething(String url, String method) {
HttpRequest request = new HttpRequest();
request.open(method, url);
request.onLoad.listen((event) {
if(request.status < 400) {
try {
String json = request.responseText;
} catch(e) {
print("Error!");
}
} else {
print("Error! (400+)");
}
});
request.setRequestHeader("Accept", ApplicationJSON);
}
I'm wondering what the e variable is in the catch clause:
catch(e) {
...
}
Obviously its some sort of exception, but (1) why do we not need to specify its type, and (2) what could I add in there to specify its concrete type? For instance, how could I handle multiple types of possible exceptions in a similar way to catchError(someHandler, test: (e) => e is SomeException)?
Dart is an optional typed language. So the type of e is not required.
you have to use the following syntax to catch only SomeException :
try {
// ...
} on SomeException catch(e) {
//Handle exception of type SomeException
} catch(e) {
//Handle all other exceptions
}
See catch section of Dart: Up and Running.
Finally catch can accept 2 parameters ( catch(e, s) ) where the second parameter is the StackTrace.
How do I handle exceptions thrown in a controller when jquery ajax calls an action?
For example, I would like a global javascript code that gets executed on any kind of server exception during an ajax call which displays the exception message if in debug mode or just a normal error message.
On the client side, I will call a function on the ajax error.
On the server side, Do I need to write a custom actionfilter?
If the server sends some status code different than 200, the error callback is executed:
$.ajax({
url: '/foo',
success: function(result) {
alert('yeap');
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('oops, something bad happened');
}
});
and to register a global error handler you could use the $.ajaxSetup() method:
$.ajaxSetup({
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('oops, something bad happened');
}
});
Another way is to use JSON. So you could write a custom action filter on the server which catches exception and transforms them into JSON response:
public class MyErrorHandlerAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
filterContext.Result = new JsonResult
{
Data = new { success = false, error = filterContext.Exception.ToString() },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
and then decorate your controller action with this attribute:
[MyErrorHandler]
public ActionResult Foo(string id)
{
if (string.IsNullOrEmpty(id))
{
throw new Exception("oh no");
}
return Json(new { success = true });
}
and finally invoke it:
$.getJSON('/home/foo', { id: null }, function (result) {
if (!result.success) {
alert(result.error);
} else {
// handle the success
}
});
After googling I write a simple Exception handing based on MVC Action Filter:
public class HandleExceptionAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
{
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
filterContext.Exception.Message,
filterContext.Exception.StackTrace
}
};
filterContext.ExceptionHandled = true;
}
else
{
base.OnException(filterContext);
}
}
}
and write in global.ascx:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleExceptionAttribute());
}
and then write this script on the layout or Master page:
<script type="text/javascript">
$(document).ajaxError(function (e, jqxhr, settings, exception) {
e.stopPropagation();
if (jqxhr != null)
alert(jqxhr.responseText);
});
</script>
Finally you should turn on custom error.
and then enjoy it :)
Unfortunately, neither of answers are good for me. Surprisingly the solution is much simpler. Return from controller:
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Response.ReasonPhrase);
And handle it as standard HTTP error on client as you like.
I did a quick solution because I was short of time and it worked ok. Although I think the better option is use an Exception Filter, maybe my solution can help in the case that a simple solution is needed.
I did the following. In the controller method I returned a JsonResult with a property "Success" inside the Data:
[HttpPut]
public JsonResult UpdateEmployeeConfig(EmployeConfig employeToSave)
{
if (!ModelState.IsValid)
{
return new JsonResult
{
Data = new { ErrorMessage = "Model is not valid", Success = false },
ContentEncoding = System.Text.Encoding.UTF8,
JsonRequestBehavior = JsonRequestBehavior.DenyGet
};
}
try
{
MyDbContext db = new MyDbContext();
db.Entry(employeToSave).State = EntityState.Modified;
db.SaveChanges();
DTO.EmployeConfig user = (DTO.EmployeConfig)Session["EmployeLoggin"];
if (employeToSave.Id == user.Id)
{
user.Company = employeToSave.Company;
user.Language = employeToSave.Language;
user.Money = employeToSave.Money;
user.CostCenter = employeToSave.CostCenter;
Session["EmployeLoggin"] = user;
}
}
catch (Exception ex)
{
return new JsonResult
{
Data = new { ErrorMessage = ex.Message, Success = false },
ContentEncoding = System.Text.Encoding.UTF8,
JsonRequestBehavior = JsonRequestBehavior.DenyGet
};
}
return new JsonResult() { Data = new { Success = true }, };
}
Later in the ajax call I just asked for this property to know if I had an exception:
$.ajax({
url: 'UpdateEmployeeConfig',
type: 'PUT',
data: JSON.stringify(EmployeConfig),
contentType: "application/json;charset=utf-8",
success: function (data) {
if (data.Success) {
//This is for the example. Please do something prettier for the user, :)
alert('All was really ok');
}
else {
alert('Oups.. we had errors: ' + data.ErrorMessage);
}
},
error: function (request, status, error) {
alert('oh, errors here. The call to the server is not working.')
}
});
Hope this helps. Happy code! :P
In agreement with aleho's response here's a complete example. It works like a charm and is super simple.
Controller code
[HttpGet]
public async Task<ActionResult> ChildItems()
{
var client = TranslationDataHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("childItems);
if (response.IsSuccessStatusCode)
{
string content = response.Content.ReadAsStringAsync().Result;
List<WorkflowItem> parameters = JsonConvert.DeserializeObject<List<WorkflowItem>>(content);
return Json(content, JsonRequestBehavior.AllowGet);
}
else
{
return new HttpStatusCodeResult(response.StatusCode, response.ReasonPhrase);
}
}
}
Javascript code in the view
var url = '#Html.Raw(#Url.Action("ChildItems", "WorkflowItemModal")';
$.ajax({
type: "GET",
dataType: "json",
url: url,
contentType: "application/json; charset=utf-8",
success: function (data) {
// Do something with the returned data
},
error: function (xhr, status, error) {
// Handle the error.
}
});
Hope this helps someone else!
For handling errors from ajax calls on the client side, you assign a function to the error option of the ajax call.
To set a default globally, you can use the function described here:
http://api.jquery.com/jQuery.ajaxSetup.