【发布时间】:2016-10-01 11:52:50
【问题描述】:
我正在创建一个 Angular 2 组件,当使用某种可观察模式时,Angular 的更改检测对我不起作用。它看起来像这样:
let getResult$ = this.http.get('/api/identity-settings');
let manager$ = getResult$
.map((response) => /* -- create manager object -- */);
let signinResponse$ = manager$
.flatMap(manager => manager.processSigninResponse());
this.readyToLogin$ = manager$.map(() => true).startWith(false);
this.isLoggedIn$ = signinResponse$.map(() => true).startWith(false);
然后在我的模板中:
<h1>Ready to Log In: {{readyToLogin$ | async}}</h1>
<h1>Logged In: {{isLoggedIn$ | async}}</h1>
由于readyToLogin$ Observable 基于一组同步操作,这些操作是为了响应http.get()(Angular “猴子补丁”以确保它知道何时需要检测更改)而发生的,因此“准备记录In”消息在适当的时候切换到true。
但是,由于processSignInResponse() 产生Promise<>,任何订阅flatMap 结果的事件都与http 请求的完成事件异步发生。因此,它需要手动干预来通知我的组件的区域它需要检查更改。
如何以NgZone 知道在解决任何订阅后检测更改的方式包装signInResponse$ observable?
更新
Brandon 的回答一直有效,直到我更新到 RC5,此时一切都停止了。结果是the 3rd-party library I was using borked Zone.js。一旦解决了这个问题,就根本不需要使用解决方法——内置的猴子补丁就可以了!
【问题讨论】:
-
Promise通常不会导致 NgZone 出现问题。我已经看到它在Promise从错误的库导入时会导致此类问题的问题中提到(我正在使用 Dart,但不知道有关 polyfill 和 TS/JS 的东西的详细信息)。此外,如果发出可观察事件的代码以某种方式在 Angulars 区域之外运行,那么更改检测就会以这种方式中断。 -
@GünterZöchbauer:据我了解,
Promises 通常会通过一些已经“猴子修补”以与 Zone.js 一起使用的事件来解决。例如,一个 Angular HTTP 请求或一个 DOM 事件处理程序触发,导致一个 Promise 被解析,并且在解析该 Promise 的同步过程中,发生的任何动作都发生在区域运行的上下文中。但是我正在使用的这个库必须在某种尚未被猴子修补的事件之后解决它的承诺。 -
是的,类似的。
-
@StriplingWarrior 你的编辑是什么意思?角度的内置行为刚刚起作用吗?角度怎么可能知道?没有意义
-
@Ced:Angular 依赖于 Zone.js,它使用 polyfill 来检测浏览器事件何时会导致更改发生。当我以覆盖这些 polyfill 的方式导入库时,Zone 无法检测到其中一个事件何时发生。当我解决这个问题时,AJAX 响应被 Zone 正确检测到,这告诉 Angular 发生了一些事情。