I'm using Angular 4+, and I noticed Angular is not updating the binded value before I call Observable.subscribe() when the Observable resolves immediately (synchronously?). In other places this works fine, because a network call delays the Observable completion long enough for the initial binding change to take effect in Angular.
https://plnkr.co/edit/LV0On7?p=preview
//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");
}
}
Without Observable.delay(), console prints:
set isCallComplete = false
set isCallComplete = true
isAlertVisible() binding updating: true
isAlertVisible() binding updating: true
When using Observable.delay(), console correctly prints:
set isCallComplete = false
isAlertVisible() binding updating: false
isAlertVisible() binding updating: false
set isCallComplete = true
isAlertVisible() binding updating: true
isAlertVisible() binding updating: true
1) Why does Angular detect the initial property binding (isCallComplete = false) when using Observable.delay(0).subscribe() and not Observable.subscribe()?
2) What is the best solution to bind to a busy property value before a Observable.subscribe() call?
答案 0 :(得分:2)
Because Angular never gets the chance to check the value of isCallComplete
.
Your Observable's subscribe callback gets executed right after it is created.
Using delay(0)
would be the equivalent of using setTimeout(()=>/*...*/,0)
, thus delaying the execution of the subscribe callback after the current synchronous code has executed (in this case Angular checking your component's values)