Node Domains
postmortem
注意:
- 从文档得知:
- 如果使用 domains,所有触发的事件对象(包括流对象,比如 request,response 等)都会在创建时隐式地与激活的 domain 绑定。
- 我认为不应该这么做,更好的做法是在创建监听函数时绑定而不是在事件触发时绑定
- 如果使用 domains,所有触发的事件对象(包括流对象,比如 request,response 等)都会在创建时隐式地与激活的 domain 绑定。
- Domains 在同步任务重的调用栈组合的很好,但是在异步任务中,只有最上层的 domains 会被存储。
- 这一点与 zone 一致,但是 Domains 无法将其组合起来
- 在讨论 zone 的时候,区分 zone 的调用栈和 zone 的构成是很重要的,看下面的例子
let logs = [];
let zoneA = Zone.current.fork({
name: 'zoneA',
onInvoke: function(delegate, currentZone, targetZone, callback, applyThis, applyArgs) {
logs.push('zoneA onInvoke');
return delegate.invoke(targetZone, callback, applyThis, applyArgs);
}
});
let zoneB = Zone.current.fork({
name: 'zoneB',
onInvoke: function(delegate, currentZone, targetZone, callback, applyThis, applyArgs) {
logs.push('zoneB onInvoke');
return delegate.invoke(targetZone, callback, applyThis, applyArgs);
}
});
let zoneAChild = zoneA.fork({
name: 'zoneAChild',
onInvoke: function(delegate, currentZone, targetZone, callback, applyThis, applyArgs) {
logs.push('zoneAChild onInvoke');
return delegate.invoke(targetZone, callback, applyThis, applyArgs);
}
});
zoneA.run(() => {
zoneB.run(() => {
zoneAChild.run(function test() {
logs.push('begin run' + Zone.current.name);
console.log('logs', logs);
const error = new Error();
console.log('trace', error.stack);
});
});
});
在这个例子中,
- zone 的调用栈是
-> zoneA -> zoneB -> zoneAChild,你可以在 error.stack 上找到这些 zone 的转移过程。 zone 的组成是, zoneAChild -> zoneA -> rootZone,所以在这个例子中, zoneB 的回调不会被触发
- 创建新的 zone 时,他是当前 zone 的子 zone ,而创建 domain 时,他是独立的。
译注: 意思是你可以在调用栈中看到代码执行从 rootZone 转移到 zoneA 再到 zoneB 再到 zoneAChild,如果发生错误你可以很快找到原因。 但是实际执行时,代码其实是在最后交给的 zoneAChild 中执行的,因此只有 zoneAChild 的回调会被触发,而 zoneAChild 是 zoneA 的子 zone,因此 zoneA 的回调也会被触发,同理,rootZone 的回调也会被触发。
- 创建新的 zone 时,他是当前 zone 的子 zone ,而创建 domain 时,他是独立的。