【问题标题】:External promises don't trigger Angular2 change detection (UPDATE: they do)外部承诺不会触发 Angular2 变更检测(更新:他们会)
【发布时间】:2016-08-09 15:49:05
【问题描述】:

我正在开发一个electron 应用程序,其客户端是用Angular2 编写的。

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

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

我很确定我知道为什么会发生这种情况:我在 Angular 之外用电子代码(即main process)创建 Bluebird Promises,而这些不是区域感知的,所以他们不会通知变化的角度。

不过,我不知道如何解决它。我可以做些什么来在我的电子代码中创建区域感知承诺,以避免一直手动运行更改检测?我能否以某种方式将我的 Bluebird Promise 转换为 Zone 感知 Promise?

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

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

【问题讨论】:

  • 主进程不就是在浏览器之外运行的进程吗?我认为那里的任何承诺都不会触发浏览器的变化。
  • 我期待他们这样做,因为即使我在主进程中创建 Promise,我也会请求它们并在 Angular 端添加 .then() 处理程序。

标签: javascript angular typescript electron bluebird


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 感谢您的回答。 zone.run()(和detectChanges())并没有那么不好,但我们必须记住在正确的地方调用它。无论如何,这就是我们现在要做的。我的问题更多的是关于是否有一种方法可以让 bluebird promise 自动表现得像 angular promise(这有效),因为 bluebird promise 有一堆有用的特性,而原生的 promise 没有。
  • 我不知道蓝鸟的承诺。正常的承诺在 Angular2 AFAIK 中没有做任何特别的事情,只是因为在浏览器中完成了异步调用,通常会调用 .then(...),这是 Angulars 区域收到通知然后运行更改检测的原因。我希望bluebird 承诺同样有效。如果 bluebird 源代码库中的错误报告不起作用,也许它可能是一个好主意。
  • 我检查了我在 Chrome 的开发控制台中创建的常规 promise,它实际上似乎是一个 ZoneAwarePromise,它是 zone.js 提供的 promise 的特殊包装器。这就是为什么我认为它们很特别。
  • 好吧,不知道。那时我会假设相同。
【解决方案2】:

正如 EDIT #2 中所解释的,问题在于在主电子过程中创建一个 Promise 使该 Promise 不感知区域。从 Angular 创建 Promise 解决了这个问题。

【讨论】:

    猜你喜欢
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 2017-04-23
    • 2020-05-16
    • 2016-09-01
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多