Javascript 角度绑定在可观察调用之前不改变

Javascript 角度绑定在可观察调用之前不改变,javascript,angular,rxjs,observable,Javascript,Angular,Rxjs,Observable,我使用的是Angular 4+,我注意到Angular在调用Observable.subscribe()之前没有更新绑定值,因为Observable立即(同步地)解析。 在其他地方,这可以很好地工作,因为网络调用延迟可观察的完成足够长的时间,以便初始绑定更改在角度上生效 //我们的根应用程序组件 从'@angular/core'导入{Component,VERSION}; 从“rxjs/Observable”导入{Observable}; 导入“rxjs/add/observable/of”;

我使用的是Angular 4+,我注意到Angular在调用Observable.subscribe()之前没有更新绑定值,因为Observable立即(同步地)解析。 在其他地方,这可以很好地工作,因为网络调用延迟可观察的完成足够长的时间,以便初始绑定更改在角度上生效

//我们的根应用程序组件
从'@angular/core'导入{Component,VERSION};
从“rxjs/Observable”导入{Observable};
导入“rxjs/add/observable/of”;
导入“rxjs/add/operator/delay”;
@组成部分({
选择器:“我的应用程序”,
模板:`
{{name}}
可立即观察到的呼叫
延迟可观测呼叫
异步操作成功!
`,
})
导出类AppComponent{
名称:字符串;
private isCallComplete=false;
isAlertVisible():布尔值{
log(“isAlertVisible()绑定更新:”,this.isCallComplete);
返回此。isCallComplete;
}
构造函数(){
this.name=`Angular!v${VERSION.full}`
}
onAlertClickedNoDelay(){
this.isCallComplete=false;
log(“set isCallComplete=false”);
可观察的(“某些数据”)。订阅(数据=>{
this.isCallComplete=true;
log(“set isCallComplete=true”);
});
}
onAlertClickedDelay(){
this.isCallComplete=false;
log(“set isCallComplete=false”);
可观察的(“某些数据”)。延迟(0)。订阅(数据=>{
this.isCallComplete=true;
log(“set isCallComplete=true”);
});
}
onAlertClose(){
this.isCallComplete=false;
log(“set isCallComplete=false”);
}
}
没有可观察的.delay(),console打印:

设置isCallComplete=false
设置isCallComplete=true
isAlertVisible()绑定更新:true
isAlertVisible()绑定更新:true

使用Observable.delay()时,console会正确打印:

设置isCallComplete=false
isAlertVisible()绑定更新:false
isAlertVisible()绑定更新:false
设置isCallComplete=true
isAlertVisible()绑定更新:true
isAlertVisible()绑定更新:true

1) 为什么Angular在使用Observable.delay(0.subscribe()和not Observable.subscribe()时检测初始属性绑定(isCallComplete=false)


2) 在Observable.subscribe()调用之前绑定到忙碌属性值的最佳解决方案是什么?

因为Angular从来没有机会检查
isCallComplete
的值

您的Observable的subscribe回调在创建后立即执行


使用
delay(0)
相当于使用
setTimeout(()=>/*…*/,0)
,从而在当前同步代码执行后延迟订阅回调的执行(在这种情况下,检查组件的值)

您可以使用中建议的方法之一在订阅可观察对象之前触发更改检测。谢谢,ChangeDetectorRef.detectChanges()似乎是最好的解决方法。虽然我不喜欢在任何地方使用isBusy属性,但谢谢你,因为这证实了我所猜测的变化检测正在发生。为了安全起见,我将在可观察调用之前手动通知Angular有关属性更改的信息。
//our root app component
import {Component, VERSION} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/delay';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>{{name}}</h2>
      <button class="btn btn-primary" (click)="onAlertClickedNoDelay()">Call Observable Without Delay</button>
      <button class="btn btn-primary" (click)="onAlertClickedDelay()">Call Observable With Delay</button>

      <alert *ngIf="isAlertVisible()" type="success" dismissible="true" (onClose)="onAlertClose()">
          Async action successful!
      </alert>
    </div>
  `,
})
export class AppComponent {
  name:string;
  private isCallComplete = false;
  isAlertVisible(): boolean {
    console.log("isAlertVisible() binding updating: ", this.isCallComplete);
    return this.isCallComplete;
  }
  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }

   onAlertClickedNoDelay() {
    this.isCallComplete = false;
    console.log("set isCallComplete = false");
    Observable.of("some data").subscribe(data => {
      this.isCallComplete = true;
      console.log("set isCallComplete = true");
    });
  }

   onAlertClickedDelay() {
    this.isCallComplete = false;
    console.log("set isCallComplete = false");
    Observable.of("some data").delay(0).subscribe(data => {
      this.isCallComplete = true;
      console.log("set isCallComplete = true");
    });
  }

  onAlertClose() {
    this.isCallComplete = false;
    console.log("set isCallComplete = false");
  }
}