mseddon
mseddon

Reputation: 1885

Futures/Promises, and tracking down bugs

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

Answers (1)

Seth Ladd
Seth Ladd

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

Related Questions