I want to put in a handler that will catch all unhandled errors in a Polymer app.
I figured Zone would be the trick so tried
void main() {
runZoned(() => initPolymer(), onError: (e, stackTrace) {
_log.shout('TOP ZONE', e, stackTrace);
});
}
But that doesn't work. The errors never get to this error handler.
Not sure if this relates to http://code.google.com/p/dart/issues/detail?id=15854
How do people handle this?
How about using Window.onError.
import 'dart:html';
main() {
window.onError.listen((ErrorEvent e) => print(e.message));
throw 'boom!';
}
So I know we have gotten error handling to work using the following construct:
runZoned(() {
return initPolymer().run(() => Polymer.onReady
.then(doSomeStuff)
.whenComplete(doSomeCompleting));
},
onError: (err, [stackTrace]) {
logger.severe("Received an error", err, stackTrace);
});
I have posted it in the interest of helping you quickly. I dont have a great explanation off the top of my head why your version isn't working at the moment. Ill do some digging and see if I can work out what is really different.
Related
topBarClient.request(settings).then(
function (data) {
console.log("data",data);
showTaskData(data);
if (data.status === 200) {
onSuccess(JSON.parse(data.responseText));
} else {
onFailure(data.status);
}
},
function (response) {
console.log("error", response);
onFailure(response.status);
}
);
onFailure is working but not able to get the error out
Is there a way to test this locally?
console.log works fine, if it's not working then it is not getting called probably due to some exception in the line above console.log.
If you face any problem you can render html component like div to dislplay the text for debugging purpose.
If I have nested async* streams, exceptions do not appear to be catchable, which is counterintuitive.
An example:
void main() {
getString().listen(print);
}
Stream<String> getString() async* {
try {
yield* asyncStarError();
yield await asyncError();
} catch (err) {
yield 'Crash';
}
}
Stream<String> asyncStarError() async* {
throw Exception('A Stream error happened');
}
Future<String> asyncError() async {
throw Exception('A Future error happened');
}
This outputs:
Uncaught Error: Exception: A Stream error happened
Crash
So the exception thrown by asyncStarError is not caught, while the Future is caught as expected. Can anyone explain why?
You can observe the behaviour in dartpad: https://dartpad.dartlang.org
The yield* forwards all events from the stream it yields, including errors.
So, asyncStarError() produces a stream with an error event, and yield* forwards that error to the stream returned by getString, and then the getString.listen(print); does not add a handler so the error becomes uncaught.
(I'm guessing you're running this in a browser since that uncaught error doesn't crash the program.)
After that, the yield await asyncError() never yield anything. The await asyncError() itself throws, before reaching the yield, and that error is then caught by the catch which yields crash.
If you want to catch the errors of a stream, you need to actually look at the events, not just use yield* to forward them all blindly, including error events.
For example:
await for (var _ in asyncStarError()) {
// Wohoo, event!
}
would make the error from the asyncStarError stream an error at the loop. It would then be caught and you'd print "Crash".
TL;DR: The yield* operation forwards error events, it doesn't raise them locally.
Since yield * forwards them like #lrn said, you can catch them in main just fine. Or wherever you are consuming them.
void main() {
getString().listen(print).onError((e) => print('error caught: $e'));
}
Stream<String> getString() async* {
try {
yield* asyncStarError();
yield await asyncError();
} catch (err) {
yield 'Crash';
}
}
Stream<String> asyncStarError() async* {
throw Exception('A Stream error happened');
}
Future<String> asyncError() async {
throw Exception('A Future error happened');
}
this prints:
error caught: Exception: A Stream error happened
Crash
The difference is that async generator (async*) exceptions cannot be caught by surrounding it with try/catch.
Instead, you should use the callback handleError to achieve the behaviour you are looking for.
To go further, you may be interested in using runZonedGuarded.
In Electron if I throw an error anywhere on the backend it goes to a custom window. Trying to find a way to catch that to push to a custom area in my app I've found that I can detect the process with process.on('uncaughtException'). However I'm stuck trying to run a sender to send either the error or the report. What I've tried:
ipcMain.on('main', async (e, data) => {
try {
await someModule(data)
process.on('uncaughtException', err => e.sender.send('error', err.message))
return e.sender.send('audit', 'No issues found')
} catch (err) {
console.log(err)
}
})
module.js:
module.export = data => {
throw Error('this is a test')
}
In the above I'm sending both get both errorandaudit` to renderer. I've researched for a way to pass 'uncaughtException' to a ternary but I'm not able to find any docs on how to condition for 'uncaughtException' but I did try:
process.on('uncaughtException', err => {
if (err) return e.sender.send('error', err.message)
return e.sender.send('audit', 'test complete')
})
and the above only works if an error is present, research:
Catch all uncaughtException for Node js app
Nodejs uncaught exception handling
Node.js Uncaught Exception - Passing more details
In Electron how can I intercept the error to pass it to renderer from main without throwing the default error window?
If you use ipcMain.handle you will be able to handle errors in the renderer process like this
// Main process
ipcMain.handle('my-invokable-ipc', async (event, data) => {
await someModule(data)
return 'No issues found'
})
// Renderer process
async () => {
try {
const result = await ipcRenderer.invoke('my-invokable-ipc', data)
console.log(result) // 'No issues found' if someModule did not throw an error
} catch (err) {
// you can handle someModule errors here
}
}
Update: An issue with this approach is that the error emitted to the renderer process is serialized and it gets printed even though it's handled with a try/catch.
To fix this, you can also handle the errors in the main process
// Main process
ipcMain.handle('my-invokable-ipc', async (event, data) => {
try {
await someModule(data)
return 'No issues found'
} catch (err) {
// handle someModule errors and notify renderer process
// return err.message or any other way you see fit
}
})
// Renderer process
async () => {
const result = await ipcRenderer.invoke('my-invokable-ipc', data)
console.log(result) // 'No issues found' if someModule did not throw an error
}
import 'dart:async';
void main() {
divide(1, 0).then((result) => print('1 / 0 = $result'))
.catchError((error) => print('Error occured during division: $error'));
}
Future<double> divide(int a, b) {
if (b == 0) {
throw new Exception('Division by zero');
}
return new Future.value(a/b);
}
Currently I am learning how to work with futures in Dart and I got stucked on such an easy example. My future throws exception when user tries to perform division by zero. However, .catchError doesn't handle my exception. I got unhandled exception with a stack trace instead. I'm pretty sure that I am missing something obvious but can't understand what exactly.
As I understand, there is another way to handle error:
divide(1, 0).then((result) => print('1 / 0 = $result'),
onError: (error) => print('Error occured during division: $error'));
to use named optional argument - onError. Doing like this still leads to unhandled exception.
I would like to clarify one more thing. Am I right? - The only difference between these 2 approaches is that .catchError() also handles errors thrown by inner futures (futures that are called inside then() method of the outer future) while onError only catches errors thrown by the outer future?
Dmitry
Thank you.
Your error handling didn't work because the error is thrown in the synchronous part of your code. Just because the method returns a future doesn't mean everything in this method is async.
void main() {
try {
divide(1, 0)
.then((result) => print('1 / 0 = $result'));
} catch (error) {
print('Error occured during division: $error');
}
}
If you change your divide function like
Future<double> divide(int a, b) {
return new Future(() {
if (b == 0) {
throw new Exception('Division by zero');
}
return new Future.value(a / b);
});
}
you get an async error and your async error handling works.
An easier way is to use the new async/await
main() async {
try {
await divide(1, 0);
} catch(error){
print('Error occured during division: $error');
}
}
try at DartPad
and another advantage is this works in both cases.
import 'dart:io';
import 'dart:async';
void main() {
HttpClient client = new HttpClient();
client.getUrl(Uri.parse('http://api.dartlang.org/docs/releases/latest/dart_io/HttpClientResponse.html'))
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
response.listen(print, onError: (e) {
print('error: $e');
});
});
}
The code above doesn't work, using similar method to listen like pipe and fold also throws an exception => Breaking on exception: The null object does not have a method 'cancel'.
Update
Here's the code example for when connect to local machine.
import 'dart:io';
import 'dart:async';
void main() {
HttpServer.bind('127.0.0.1', 8080)
.then((HttpServer server) {
server.listen((HttpRequest request) {
File f = new File('upload.html');
f.openRead().pipe(request.response);
});
HttpClient client = new HttpClient();
client.getUrl(Uri.parse('http://127.0.0.1:8080'))
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
response.listen(print, onError: (e) {
print('error: $e');
});
});
});
}
It prints out the bytes first and then throw an exception Breaking on exception: The null object does not have a method 'cancel'.
Dart Editor version 0.7.2_r27268. Dart SDK version 0.7.2.1_r27268. On Windows 64bit machine.
Your example works on my machine.
Please specify your Dart version and other system properties that could help debug the problem.
The code presented looks fine, and I have not been able to reproduce the error on either 0.7.2.1 nor bleeding edge. Do you know whether you network has any kind of proxy setup which could cause a direct HTTP connection to fail? You could try connecting to a server on your local machine instead. If it still fails I suggest opening a bug on https://code.google.com/p/dart/issues/list with detailed information.