Dart-Zone

Dart 是单线程模型,相对于 JavaScript,其也有 microTaskQueueeventTaskQueue.

Zone 代表某个环境的稳定跨异步环境调用.

代码通常都执行在一个 zone中,如Zone.current.而main函数通常运行在默认的Zone.root上下文中.
通过 runZoned 创建一个新zoneZone.run 将代码运行到一个由 Zone.fork创建的上下文中.

开发者可以通过覆盖一个存在zone的一些方法来创建一个新zone.如自定义zone可以替换或修改print、timers、
micortasks、uncaught erros 的默认行为.

Zone类不可以被继承.可以使用 fork 存在的 zone,通常是Zone.currentZoneSpecification来自定义zone.这和继承Zone类来创建新的zone类似.

异步回调总是运行在其被规定的zone上下文中.使用一下步骤实现:

  • 首先使用registerCallbackregisterUnaryCallbackregisterBinaryCallback中的一个注册.zone就就可以记录此callback或修改它(返回一个不同的callback).执行注册的代码(如 Future.then)也会记住当前的zone,之后callback就可以在此zone中运行.
  • 之后在上面保留的zone中运行注册的callback.
    这些通常都有平台处理,用户无需操心.如果要根据底层提供的功能或native extensions开发自定义的异步规则,则必须实现上面两步.

bindCallbackbindUnaryCallbackbindBinaryCallback 则简化了上面的步骤,直接调用即可.

bindCallbackGuardedbindUnaryCallbackGuardedbindBinaryCallbackGuarded可以通过Zone.runGuarded来调用.

Dart 构造方法不可见的实现方式: Zone._();

所有的隔离入口函数被调用时(mainspawned 函数)都运行在根zone(即 Zone.current等于Zone.root).如果没有创建自定义的zone,后面的代码都会运行在此根zone中.

如果异步回调如FutureStream没有捕获异常,则会调用zone.handleUncaughtError来捕获异常.

error zone(Zone.current.errorZone)是处理未捕获异常的地方.异步异常不会传递到不同的error handler.

1
2
3
4
5
6
7
8
9
10
11
import 'dart:async';

main() {
var future;
runZoned(() {
future = Future.error("asynchronous error");
},onError:(e){print(e);});
future.catchError(e) {
throw "is never reached";
}
}