私のAngular 2アプリケーションには、サービス内に2つのメソッド(GetCategories()
およびGetCartItems()
)があり、これらのメソッドの両方がObservable
sを返します。
これらの2つのメソッドをコンポーネントから次々に呼び出すために、以下のコードを記述しました。
_ 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()
のsubscribe()
内からGetCategories()
を呼び出すと、これは適切なアプローチではないと思います。これは一種のコールバック地獄です。
これをより良い方法で実装する方法についてのアイデア(Promise
sでのthen()
の連鎖など)?
GetCartItems
は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;
});
これは最も一般的にconcat()
、concatMap()
、または最終的にはconcatAll()
を使用して行われます。
_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 を参照してください