4

我正在尝试在节点中使用angular/zone.js编写一个简单的演示,但由于某种原因,beforeTaskorafterTask都没有被调用。

这是我正在运行的代码:

require('zone.js');

function foo () {
  Zone.current.fork({
    name: 'foo_zone',
    
    beforeTask: function () {
      console.log('~~~ ZONE START ~~~');
    },
    
    afterTask: function () {
      console.log('~~~ ZONE END ~~~');
    }
  })
    .run(function () {
      console.log('in the zone');
      console.log('Zone.current.name', Zone.current.name); // prints foo_zone
      setTimeout(() => {
        console.log('timeout is up');
      }, 1000);
    });
}
foo();

现在在区域内一切都打印正常,包括区域名称,但没有调用任何钩子。

我是否缺少 zone.js + node.js 的基本内容?

(运行节点 v5.0.0,zone.js 0.6.23)

4

2 回答 2

1

这是示例存储库。 https://github.com/JiaLiPassion/zone-node

首先,您需要使用最新版本的 zone.js,并且要在 nodejs 中使用 zone.js,您应该需要 zone-node.js,以下是运行示例。

require('./zone-node.js');

function log(str) {
  Zone.root.run(function() {
    console.log(str);
  });
}
function foo() {
  Zone.current.fork({
    name: 'fooZone', 
    onScheduleTask: function(delegate, curr, target, task) {
      log('Zone begin to schedule task not async yet ' + task.source);
      return delegate.scheduleTask(target, task);
    },
    onInvokeTask: function(delegate, curr, target, task, applyThis, applyArgs) {
      log('~~~~Zone before invoke async callback~~~~' + task.source);
      delegate.invokeTask(target, task, applyThis, applyArgs);
      log('~~~~Zone after invoke async callback~~~~' + task.source);
    },
  }).run(function() {
    log('current zone, ' + Zone.current.name);
    setTimeout(function() {
      log('timeout is up, ', Zone.current.name);
    }, 100);
  });
};

foo();

在nodejs中运行后,输出将是。

current zone, fooZone
Zone begin to schedule task not async yetsetTimeout
~~~~Zone before invoke async callback~~~~setTimeout
timeout is up,
~~~~Zone after invoke async callback~~~~setTimeout
于 2017-03-18T06:49:22.060 回答
0

我遇到了同样的问题。如果您像我一样,您可能会在 zone.js 存储库中看到一个像这样的示例,并看到使用了 beforeTask 和 afterTask 的钩子。但是,如果您查看API并查看 ZoneSpec 接口(它指定 zone.fork 将识别的挂钩),那么任何地方都没有提到 beforeTask 或 afterTask。这可能是因为自从编写该示例以来,这些钩子已被重命名/重构,只是尚未更新

但是,API 中提到了一个名为“onInvokeTask”的钩子,定义为:

onInvokeTask?: (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, applyThis: any, applyArgs: any) => any;

当在 ZoneSpec 中给出时,它将被调用来代替正在调用的任务,所以我尝试了这样的事情:

require('zone.js');

function foo () {
  Zone.current.fork({
    name: 'foo_zone',

    onInvokeTask: function (parentZoneDelegate, currentZone, targetZone, task, applyThis, applyArgs) {
      console.log('~~~ ZONE START ~~~');
      parentZoneDelegate.invokeTask(targetZone, task);
      console.log('~~~ ZONE END ~~~');
    },
  })
    .run(function () {
      setTimeout(function() {
        console.log('in the zone');
        console.log('Zone.current.name', Zone.current.name); // prints foo_zone
        setTimeout(() => {
          console.log('timeout is up');
        }, 1000);
      }, 0);
    });
}
foo();

打印所需的结果:

~~~ ZONE START ~~~
in the zone
Zone.current.name foo_zone
~~~ ZONE END ~~~
~~~ ZONE START ~~~
timeout is up
~~~ ZONE END ~~~

需要注意的几点:

  1. 与示例中的 beforeTask 和 afterTask 似乎在任务运行之前和之后被调用不同,onInvokeTask 钩子被调用来代替运行任务,所以如果你想要任务,你必须指定在该钩子中运行任务运行,因此parentZoneDelegate.invokeTask(targetZone, task);

  2. 我将代码包装在 run 函数中,setTimeout(function() { ... }, 0)因为 run 函数中的代码实际上是在与示例中的所有代码相同的任务中调用的(除了在新任务中运行的 setTimeout 调用中的代码)和onInvokeTask 钩子不适用于当前任务,因为当前任务已经被调用。这意味着~~~ ZONE START ~~~并且~~~ ZONE END ~~~只会timeout is up在行周围打印。

于 2016-11-25T05:19:42.030 回答