关于angular:何时使用Ngzone.run()?

When to use Ngzone.run()?

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

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

如该答案所述。

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

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

我在NGXS的状态缩减器中使用router.navigate来解决此问题。

我的问题是:

有人可以解释我到底什么时候需要将代码包装在NgZone中吗?

调试了几个小时并意识到我的代码不在zone上下文之外,这很烦人。


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

  • 当某个事件被触发时,它会告诉angular检测变化。
  • 如果您正在使用mouseUp()或mouseDown()事件,则在每次更改时,它都会告诉angular检测更改。
  • 如果我们不希望这些更改在运行时以角度进行(这会降低应用程序的性能),则可以在角度区域之外运行它。
  • 与此相反,如果我们渴望获得每个更新,则可以使用ngZone.run()。表示它将正常运行更改检测。

Angular本身在引擎盖下使用ngZone来检测更改

因此,如果我们走出了角度区域,那么要返回,我们使用ngZone.run()


Zone.js is an execution context for tracking and intercepting async operations
like: DOM events (click, keydown, keyup, etc), setTimeout, setInterval. XMLHttpRequests

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

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

因此,基本上可以回答您的问题:处理与Zone.js中Angular的运行上下文无关的任何第三方库时(除非您确定不需要执行上下文,并且可以使用NoopNgZone在不使用上下文的情况下进行工作)

资源


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

1
2
3
4
5
6
7
8
it('should redirect if condition true, fakeAsync(() => {
  router.navigate(['']);
  fixture.ngZone.run(() => {
    component.redirectIfConditionTrue();
  });
  tick();
  expect(location.path()).toBe('/AgentLeadsManager');
}));
  • 资料来源:这是我曾经唯一一次使用过它