@Component({ selector: 'my-app', template: ` <div> <h1>Cascading Async Operations</h1> <hr /> <div> <table> <tr> <td style='white-space: nowrap;'>Random Number from first Observable:</td> <td>{{observableRandResult}}</td> </tr> <tr> <td style='text-align: right;'>x 2:</td> <td>{{observableCalcResult1}}</td> </tr> <tr> <td style='text-align: right;'>x 3:</td> <td>{{observableCalcResult2}}</td> </tr> </table> Top-Level Observable Status: <span [style.color]="mainObservableStatus === 'Idle' ? 'Blue' : 'Red'">{{mainObservableStatus}}</span> <input type="button" [disabled]="calculating" value="Trigger" (click)="doCascadingAsyncOperations(false)" /> <input type="button" [disabled]="calculating" value="Trigger and Wait" (click)="doCascadingAsyncOperations(true)" /></div> </div> `, }) export class App { observableRandResult: number; observableCalcResult1: number; observableCalcResult2: number; mainObservableStatus: string = "Idle"; calculating: boolean = false; constructor() {} doCascadingAsyncOperations(waitForAll: boolean): void { this.calculating = true; this.observableRandResult = null; this.observableCalcResult1 = null; this.observableCalcResult2 = null; this.mainObservableStatus = "Running"; if (waitForAll) { this._cascadingAsyncOperationsWorker2().subscribe((result) => { this.mainObservableStatus = "Idle"; }); } else { this._cascadingAsyncOperationsWorker1().subscribe((result) => { this.mainObservableStatus = "Idle"; }); } } _cascadingAsyncOperationsWorker1(): Observable { return new Observable(mainObserver => { setTimeout(() => { mainObserver.next((Math.random() * 100).toFixed(0)); mainObserver.complete(); }, 1000); }) .do(mainObservableResult => { this.observableRandResult = mainObservableResult; (new Observable(innerObserver1 => { setTimeout(() => { innerObserver1.next(mainObservableResult * 2); innerObserver1.complete(); }, 1000); }) .do(innerObservable1Result => { this.observableCalcResult1 = innerObservable1Result; (new Observable(innerObserver2 => { setTimeout(() => { innerObserver2.next(innerObservable1Result * 3); innerObserver2.complete(); }, 1000); }) .do(innerObservable2Result => { this.observableCalcResult2 = innerObservable2Result; this.calculating = false; })).subscribe(); })).subscribe(); }); } _cascadingAsyncOperationsWorker2(): Observable { return new Observable(wrapperObserver => { (new Observable(mainObserver => { setTimeout(() => { mainObserver.next((Math.random() * 100).toFixed(0)); mainObserver.complete(); }, 1000); }) .do(mainObservableResult => { this.observableRandResult = mainObservableResult; (new Observable(innerObserver1 => { setTimeout(() => { innerObserver1.next(mainObservableResult * 2); innerObserver1.complete(); }, 1000); }) .do(innerObservable1Result => { this.observableCalcResult1 = innerObservable1Result; (new Observable(innerObserver2 => { setTimeout(() => { innerObserver2.next(innerObservable1Result * 3); innerObserver2.complete(); }, 1000); }) .do(innerObservable2Result => { this.observableCalcResult2 = innerObservable2Result; this.calculating = false; wrapperObserver.next(); wrapperObserver.complete(); })).subscribe(); })).subscribe(); })).subscribe(); }); } }