2016-12-28 123 views
6

我的Angular 2應用程序在服務中有2個方法[GetCategories()和GetCartItems()],並且這兩個方法都返回 Observables。訂閱多個Observable in Angular 2

爲了這兩個方法調用陸續從我的組件,我寫了下面的代碼從內部GetCategories()的認購

ngOnInit() 
{ 
    this.appService.GetCategories().subscribe((data) => { 
     this.appService.categories = data; 


     this.appService.GetCartItems().subscribe({ 
                next: (data) => { this.appService.cart = data}, 
                error: (err) => { this.toaster.error('cart==>' + err)} 

               }) 

    });  
} 

基本上調用GetCartItems,我覺得這是不正確的方法,這是一種回調地獄。

任何想法如何以更好的方式實現這個(如鏈接「然後」承諾)?

+1

http://stackoverflow.com/questions/36712659/angular-2-two-backend-service-calls-on-success-of-first-service/36712707#36712707 – echonax

回答

10

看起來像GetCartItems doens't取決於GetCategories。然後你可以使用zip

Observable 
    .zip(
     this.appService.GetCategories() 
     this.appService.GetCartItems() 
    ) 
    .catch(err => this.toaster.error(err)) 
    .subscribe(([categories, cartItems]) => { 
     this.appService.categories = categories; 
     this.appService.cart = cartItems; 
    }); 
+0

我覺得'Observable.combineLatest'是正確的選擇,而不是'Observable.zip'(如果我理解了這個問題)。自寫這篇文章以來,事情可能會發生變化。當我使用Observable.zip而沒有第三個參數時,其中一個輸入是未定義的,取決於訂閱何時觸發。 –

7

這與concat()concatMap()或最終concatAll()最典型的是做取決於你的用例,並whetrher你需要按順序或不叫這兩種服務。

function GetCategories() { 
    return Observable.timer(1000).do(() => console.log('GetCategories()')); 
} 

function GetCartItems() { 
    return Observable.timer(1000).do(() => console.log('GetCartItems()')); 
} 

console.log('start...'); 

GetCategories() 
    .concatMap(() => GetCartItems()) 
    .subscribe(() => console.log('done')); 

這將打印到控制檯:

start... 
GetCategories() 
GetCartItems() 
done 

每個項目被延遲,以顯示這些被稱爲以此起彼伏。

如果您不需要保持相同的順序,您可以使用merge()mergeMap()

見現場演示:https://jsbin.com/wawajob/1/edit

注意,使用zip()可能有意外的行爲。見https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/zip.md