外部承诺不会触发 Angular2 更改检测(更新:它们会触发)

External promises don't trigger Angular2 change detection (UPDATE: they do)

我正在研究 electron application, whose client side is written in Angular2

我有很多人遇到过的经典问题(例如 and here), namely that I'm updating my component's data, but the view doesn't get updated because Angular doesn't know that the data has changed. The solutions people suggest (see above and also )是手动 运行 更改检测,在整个组件树或其中的一部分(类似于 Angular 1 的 $rootScope.$digest$scope.$digest)。

但是,我想避免将所有数据更改包装在 zone.run() 调用中,因为它稍微违背了使用 Angular.

的目的

我很确定我知道为什么会这样:我在 Angular 之外,在电子代码(即 main process)中创建 Bluebird Promise,而这些不是 Zone知道,所以他们不会通知 Angular 更改。

不过我不知道怎么解决。我该怎么做才能在我的电子代码中创建区域感知承诺,以避免必须一直手动 运行 更改检测?我能以某种方式将我的 Bluebird Promise 转换为 Zone aware Promise 吗?

编辑:我想我错了,即使在 angular 中创建,Bluebird 承诺也不会识别区域。他们只是一般不了解区域。

编辑 2:我在之前的编辑中完全错了。 Bluebird promises 与区域一起工作得很好。但是,在电子应用程序的上下文中,在 main 电子进程中创建承诺并在 renderer 进程中使用它(其中 Angular lives), 不起作用,因为返回的承诺不是区域感知的。从 Angular 代码创建承诺有效。

Promise 不会使用 ChangeDetectionStrategy.OnPush 进行 Angular 运行 更改检测,除非您使用异步管道 ... | async.

当代码在 Angular2 之外初始化时,它 运行 在 Angular 区域之外。您可以做的是在 Angular2 代码中移动初始化或使用 ´zone.run(...)to move execution inside Angulars zone. There is nothing bad aboutzone.run(...)`.

如果执行的代码仅更改组件的局部属性,您可以对该组件使用 ChangeDetectorRef.detectChanges() 到 运行 更改检测。

如果代码导致其他组件发生变化(例如 this.router.navigate(...),则 detectChanges() 是不够的。对于这种情况,应使用 zone.run()

setTimeout(...) 触发整个应用程序的变更检测,应避免作为手动调用变更检测的方式。

正如编辑 #2 中所解释的,问题是在主要电子过程中创建承诺使得承诺无法识别区域。从 Angular 创建承诺解决了它。