关于 dart:Futures/Promises,以及追踪错误

Futures/Promises, and tracking down bugs

简而言之,Futures (dart) 或 Promises (js) 似乎为可怕的回调提供了一种模糊有用的解决方案。

对于大型软件,例如,当您正在与之交谈的服务器开始返回垃圾,触发深埋在第三方代码中的迄今为止看不见的异常时,就会出现问题。在这一点上,在一个令人难以置信的长链中的某个地方,以 catchError 终止,您将成为新的"空指针异常"之类的幸运接收者。它从哪里来的?谁知道?显然,我们不会使用这些技术神奇地获得调用堆栈,并且没有任何有用的跟踪信息 - 在这个巨大的链中,某些特定的函数可能会被调用 50 次,并且在某些任意调用时,会引发错误.

遇到这种情况时最好采用什么策略?


即将推出的名为"区域"的功能在这里应该会有所帮助。另外,请查看 getAttachedStackTrace.

此示例打印"catchError 内部":

1
2
3
4
5
6
7
8
9
10
11
12
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);
}

这个例子打印 'in onError':

1
2
3
4
5
6
7
8
9
10
11
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'));
}

这个例子打印"in onError: Illegal argument(s): testing":

1
2
3
4
5
6
7
8
9
10
11
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'));
}

此示例打印出堆栈跟踪,其中包含原始异常发生的文件和行号:

1
#0      main.. (file:///Users/sethladd/dart/zoneexperiment/bin/zoneexperiment.dart:7:20)

代码:

1
2
3
4
5
6
7
8
9
10
11
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)));
}

区域应该在 1.0 之前退出实验。

getAttachedStackTrace 的文档:http://api.dartlang.org/docs/releases/latest/dart_async.html#getAttachedStackTrace

runZoned 的文档:http://api.dartlang.org/docs/releases/latest/dart_async.html#runZonedExperimental