外部承诺不会触发Angular2变更检测(更新:他们这样做)

时间:2016-08-09 15:49:06

标签: javascript angular typescript electron bluebird

我正在使用electron应用程序,其客户端是用Angular2编写的。

我遇到很多人遇到的经典问题(例如herehere),即我更新了我的组件数据,但视图没有更新,因为Angular不知道数据已经改变。人们建议的解决方案(参见上文和here)是在整个组件树上或部分树上手动运行变更检测(类似于Angular 1' s $rootScope.$digest和{{ 1}})。

但是,我希望避免在$scope.$digest次调用中包含所有数据更改,因为它略微违背了使用Angular的目的。

我很确定我知道为什么会这样:我在Angular之外创建Bluebird Promises,在电子代码中(即main process),这些不是区域意识到,所以他们没有通知Angular这些变化。

但是,我不知道如何解决它。如何在我的电子代码中创建区域感知承诺,以避免必须始终手动运行变更检测?我能否以某种方式将我的蓝鸟承诺转换为区域感知承诺?

编辑:我认为我错了,即使在棱角分明的情况下创建,Bluebird承诺也无法识别区域。他们通常不会识别区域。

编辑2 :我在之前的编辑中完全错了。 Bluebird承诺使用区域可以正常工作。但是,在电子应用程序的上下文中,在电子过程中创建承诺并在渲染器过程中使用它(Angular生活的地方),不会工作,因为返回的承诺不是区域感知的。从Angular代码创建承诺。

2 个答案:

答案 0 :(得分:3)

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

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

如果执行的代码仅更改组件的本地属性,则可以使用ChangeDetectorRef.detectChanges()运行此组件的更改检测。

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

setTimeout(...)触发整个应用程序的更改检测,应该避免手动调用更改检测。

答案 1 :(得分:0)

正如编辑#2中所解释的那样,问题是在主电子过程中创造一个承诺使得承诺不区域感知。从Angular创建承诺解决了它。