[英]*RxJs* How to combine multiple ajax to one observable that doesn't require sequence
我有兩個 API 來獲取 Angular5 上的菜單數據,但我不知道我是否使用嵌套訂閱,getSecondMenu 函數是 RxJs 的正確方法。 有沒有人有任何想法,以下是預期結果和示例代碼:
console.log: 1. get firstMenuList 2. all done 3. get secondMenu * 3
getFirstMenu$() .do(firstMenuList => { console.log('get firstMenuList'); }) .do(firstMenuList => { firstMenuList.forEach(firstMenu => { // nested subscribe : bind to child property, let Angular auto-generate second Menu in HTML getSecondMenu$(firstMenu.ID).subscribe((secondMenu) => { firstMenu.child = secondMenu; console.log('get secondMenu'); }); }) }) .subscribe((menuList) => { console.log('all done' ); }); function getFirstMenu$() { return Rx.Observable.of([{ ID: 'menu1', child: null }, { ID: 'menu2', child: null }, { ID: 'menu3', child: null }, ]); } function getSecondMenu$(menuID) { let source = null; switch (menuID) { case 'menu1': source = [{ ID: 'subMenu1-1', }]; break; case 'menu2': source = [{ ID: 'subMenu2-1', }]; break; default: source = []; break; } const delayTime = ((Math.random() * 20) + 5) * 120; return Rx.Observable.of(source).delay(delayTime); }
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.8/dist/global/Rx.umd.js"></script>
謝謝,@Fan Cheung 談了很多關於如何組合多個 observable,總結一下你有兩種方法可以做到這一點
// componnet class myComponent { getMenu() { new sharedService().getMenu({ getFirstMenuList: () => { console.log('render first menu to template...') } }) } } // shared service class sharedService { getMenu(callback) { this.getFirstMenu$() .mergeMap(firstMenuList => { console.log('get first menu'); // if (callback.getFirstMenuList) { callback.getFirstMenuList(firstMenuList); } return Rx.Observable.from(firstMenuList); }) .mergeMap(firstMenu => this.getSecondMenu$(firstMenu.ID), (firstMenu, secondMenu) => { // console.log('get second menu'); // firstMenu.child = secondMenu return firstMenu; }) .reduce((acc, curr) => acc.concat(curr), []) .subscribe((menuList) => { console.log('all done'); }); } getFirstMenu$() { return Rx.Observable.of([{ ID: 'menu1', child: null }, { ID: 'menu2', child: null }, { ID: 'menu3', child: null }, ]); } getSecondMenu$(menuID) { let source = null; switch (menuID) { case 'menu1': source = [{ ID: 'subMenu1-1', }]; break; case 'menu2': source = [{ ID: 'subMenu2-1', }]; break; default: source = []; break; } const delayTime = ((Math.random() * 20) + 5) * 120; return Rx.Observable.of(source).delay(delayTime); } } // getTemplate new myComponent().getMenu();
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.8/dist/global/Rx.umd.js"></script>
// componnet class myComponent { getMenu() { new sharedService().getMenu().subscribe(() => { console.log('render first menu to template...'); }) } } // shared service class sharedService { getMenu() { return this.getFirstMenu$() .mergeMap(firstMenuList => { console.log('get first menu'); return Rx.Observable.from(firstMenuList); }) .mergeMap(firstMenu => this.getSecondMenu$(firstMenu.ID), (firstMenu, secondMenu) => { // console.log('get second menu'); // firstMenu.child = secondMenu return firstMenu; }) .reduce((acc, curr) => acc.concat(curr), []) .do((menuList) => { console.log('all done'); }); } getFirstMenu$() { return Rx.Observable.of([{ ID: 'menu1', child: null }, { ID: 'menu2', child: null }, { ID: 'menu3', child: null }, ]); } getSecondMenu$(menuID) { let source = null; switch (menuID) { case 'menu1': source = [{ ID: 'subMenu1-1', }]; break; case 'menu2': source = [{ ID: 'subMenu2-1', }]; break; default: source = []; break; } const delayTime = ((Math.random() * 20) + 5) * 120; return Rx.Observable.of(source).delay(delayTime); } } // getTemplate new myComponent().getMenu();
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.8/dist/global/Rx.umd.js"></script>
嘗試這個
getFirstMenu$()
.map(firstMenuList => Observable.from(firstMenuList))
.flatMap(firstMenu=> getSecondMenu$(firstMenu.ID))
.do(secondMenu => firstMenu.child = secondMenu)
.subcribe()
編輯1
getFirstMenu$()
.mergeMap(firstMenuList => Rx.Observable.from(firstMenuList))
.mergeMap(firstMenu=> getSecondMenu$(firstMenu.ID)
,(firstMenu, secondMenu) => {
firstMenu.child=secondMenu
return firstMenu
})
.reduce((acc,curr)=> acc.concat(curr) ,[])
.subscribe((menuList) => {
console.log(menuList)
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.