Reputation: 1885
For short, simple pieces of code, Futures (dart), or Promises (js), seem to offer a vaguely useful solution to the horrors of callbacks.
With large software the problem arises when for example, the server you are talking to starts returning junk, triggering a hitherto unseen exception buried deep in third party code. At this point, somewhere in an incredibly long chain of .then's, terminated with a catchError you will be the lucky recipient of something like new "Null pointer exception.". Where did it come from? Who knows? Obviously we don't magically get a call stack using these techniques, and there is no trace information that is of any use - some particular function may be called 50 times in this huge chain, and on some arbitrary invocation, an error is raised.
What strategies are best employed when confronted with this situation?
Upvotes: 2
Views: 659
Reputation: 120569
An upcoming feature called Zones should help here. Also, check out getAttachedStackTrace
.
This example prints "inside of catchError":
import 'dart:async';
void main() {
runZonedExperimental(() {
new Future.value(1)
.then((v) => v)
.then((v) => throw new ArgumentError('testing'))
.then((v) => v)
.catchError((e) => print('inside of catchError'));
},
onError: print);
}
This example prints 'in onError':
import 'dart:async';
void main() {
runZonedExperimental(() {
new Future.value(1)
.then((v) => v)
.then((v) => throw new ArgumentError('testing'))
.then((v) => v);
},
onError: (e) => print('in onError'));
}
This example printed "in onError: Illegal argument(s): testing":
import 'dart:async';
void main() {
runZonedExperimental(() {
new Future.value(1)
.then((v) => v)
.then((v) => throw new ArgumentError('testing'))
.then((v) => v);
},
onError: (e) => print('in onError: $e'));
}
This example prints out the stack trace, which contains the file and line number where the original exception occurred:
#0 main.<anonymous closure>.<anonymous closure> (file:///Users/sethladd/dart/zoneexperiment/bin/zoneexperiment.dart:7:20)
The code:
import 'dart:async';
void main() {
runZonedExperimental(() {
new Future.value(1)
.then((v) => v)
.then((v) => throw new ArgumentError('testing'))
.then((v) => v);
},
onError: (e) => print(getAttachedStackTrace(e)));
}
Zones should be moving out of experimental before 1.0.
The docs for getAttachedStackTrace: http://api.dartlang.org/docs/releases/latest/dart_async.html#getAttachedStackTrace
The docs for runZoned: http://api.dartlang.org/docs/releases/latest/dart_async.html#runZonedExperimental
Upvotes: 6