何时使用 Ngzone.run()?

Posted

技术标签:

【中文标题】何时使用 Ngzone.run()?【英文标题】:When to use Ngzone.run()? 【发布时间】:2018-12-29 12:48:07 【问题描述】:

我在我的 Angular 项目中遇到了一个错误,最终通过将我的代码包装到中解决了

this.zone.run(() => /* my code here */);

如this 回答所述。

我之前对zone的理解是,angular无法检测到第三方库的异步callbacks所做的更改,因为“它们不在angular的zone中”。如果我单击button,则触发的事件不是浏览器的本机click 事件,而是由angular 创建的自定义(已修补)click 事件,其handlerzone 中运行,因此 angular 知道其回调处理程序所做的更改。

但我无法理解通过在第三方回调中运行router.navigate() 会产生此问题(如this github 问题所示)。 Router 不是 Angular 本身的 service 吗?为什么在第三方callback调用时不自动通知angular的zone

我在 NGXS 的 state reducer 中使用 router.navigate 遇到了这个问题。

我的问题是:

谁能解释一下我什么时候需要将我的代码包装在NgZone 中?

调试了几个小时并意识到我的代码超出了zone 上下文是很烦人的。

【问题讨论】:

@dasfsa,如果事件不在“角度区域”中,角度无法检测到该事件。换句话说,Angular 可以检测到 router.navigate,但无法检测到执行 router.navigate 的事件 doc 中提供的示例确实解释了它的用法:angular.io/api/core/NgZone#example 我正在解决一些将我引导到这个 NgZone 的问题。我需要从 iframe 外部的脚本更新组件内部的属性。 我把演示放在这里:stackblitz.com/edit/… 我发现在async 函数中导航时需要this.ngZone.run(() => this.router.navigate(["login"])).then(); 【参考方案1】:

ngZone.runOutsideAngular() - 这会在角度区域之外运行代码。

当某个事件被触发时,它会告诉 Angular 来检测变化。 如果您使用的是 mouseUp() 或 mouseDown() 事件,那么在每次更改时它都会告诉 Angular 来检测更改。 如果我们不希望这些更改在 Angular 运行时发生(这会降低应用的性能),我们可以在 Angular 区域之外运行它。 与此相反,如果我们非常想获得每一个更新,那么我们可以使用 ngZone.run()。表示它将正常运行更改检测。

Angular 本身在后台使用 ngZone 来检测变化

所以,如果我们已经离开了角度区域,那么我们使用ngZone.run()返回来

【讨论】:

【参考方案2】:

ngZone.run() 在对路由进行单元测试时特别有用。

it('should redirect if condition true, fakeAsync(() => 
  router.navigate(['']);
  fixture.ngZone.run(() => 
    component.redirectIfConditionTrue();
  );
  tick();
  expect(location.path()).toBe('/AgentLeadsManager');
));
来源:这是我唯一一次使用它

【讨论】:

【参考方案3】:

Zone.js 是用于跟踪和拦截异步操作的执行上下文 比如:DOM 事件(clickkeydownkeyupetc)、setTimeoutsetIntervalXMLHttpRequests)

NgZone 只是 Zone.js 的 API 的包装 Angular 服务。

Angular 团队决定在使用 Angular 时需要执行上下文的抽象,因此他们在 Angular 中围绕它构建了 Zone.js 和包装器(非正式地 - 适配器模式)。

所以基本上回答你的问题:在处理与 Zone.js 中的 Angular 运行上下文无关的任何类型的第 3 方库时(除非你决定不需要执行上下文并且你可以工作 without 它使用NoopNgZone)

Source

【讨论】:

以上是关于何时使用 Ngzone.run()?的主要内容,如果未能解决你的问题,请参考以下文章

何时使用类别以及何时使用子类化? [关闭]

何时使用 Storyboard 以及何时使用 XIB

何时使用,何时不使用 Try Catch Final

MySQL索引的分类何时使用何时不使用何时失效?

何时使用 GetXXX() 方法以及何时使用 Getter 属性

Vuex - 何时使用 getter 以及何时使用状态