我何时应该在角度2中使用zone.run

时间:2017-09-06 02:25:32

标签: angular

我试着阅读很多关于角度2的区域。我知道角度使用zone.js进行变化检测。我看到一些代码使用了zone.run并在其中放置了一些操作。它实际上做了什么?我理解的一件事是它将这些命令作为单独的块执行。我仍然无法弄清楚zone.run的实际用途

2 个答案:

答案 0 :(得分:5)

要详细了解NgZone阅读:

  

它实际上做了什么?

Zone.run可让您更改当前区域。这是基本的例子:

console.log(Zone.current.name);  // <root>
setTimeout(() => console.log(Zone.current.name));  <root>

// we're in the <root> zone now, but when we call `run` on the instance of zone `A` we change the zone
Zone.current.fork({name: 'A'}).run(() => {
    console.log(Zone.current.name); // A
    setTimeout(() => console.log(Zone.current.name)); // A
});

// again we're back in the <root> zone now, but when we call `run` on the instance of zone `B` we change the zone   
Zone.current.fork({name: 'B'}).run(() => {
    console.log(Zone.current.name);  // B
    setTimeout(() => console.log(Zone.current.name)); // B
});

Zone.current.fork创建一个新区域。它返回对此新区域的引用,并使用run您可以在此区域内执行异步操作。您可以在上面看到setTimeout异步任务在整个时间内保持正确的区域。

Angular创建了自己的区域:

function forkInnerZoneWithAngularBehavior(zone: NgZonePrivate) {
  zone._inner = zone._inner.fork({
    name: 'angular',
    properties: <any>{'isAngularZone': true},
    ...

当你将NgZone注入类构造函数时,这个新区域就是你所获得的:

constructor (zone: NgZone) {}

当前执行区不是Angular zone(NgZone) - zone.run()时,您需要使用Zone.current.name !== 'angular'。如果是这种情况,您需要Angular不会选择从此区域安排的所有异步任务,并且它不会安排更改检测。因此,您可以切换到Angular区域以执行某些异步任务:

Zone.current.fork({name: 'A'}).run(() => {
    // this timeout won't be picked up by Angular
    setTimeout(() => console.log(Zone.current.name)); // A

     // this timeout will be picked up by Angular
     NgZone.run(() => setTimeout(() => console.log(Zone.current.name)));
});

有时您也可能会执行相反操作并在Angular区域外运行一些异步任务。使用runOutsideAngular方法:

NgZone.runOutsideAngular(()=>{ ... })

答案 1 :(得分:3)

什么是Zone.js?

区域是在异步任务中持续存在的执行上下文。您可以将其视为JavaScript VM的线程本地存储。

它是如何运作的?

zone.js修补大多数标准Web API(例如DOM事件,XMLHttpRequest ...)和nodejs API(EventEmitter,fs ...)。

它如何应用于Angular?

Angular依赖于Zone.js修补浏览器事件,以便在事件完成后触发更改检测。这允许您使用POJO(普通的旧javascript对象)。

注意:如果您想查看补丁浏览器事件的示例,请尝试执行alert(setTimeout)

您可能希望使用Zone.run手动触发Angular不知道的异步事件的更改检测。例如,您可以将Zone.run用于从第三方组件触发的自定义事件。