Reputation: 2244
I have two API to get menu data on Angular5, but I don't know if I use nested subscribe that getSecondMenu function is the correct way of RxJs. Does anyone have any idea, below is expected result and sample code:
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/[email protected]/dist/global/Rx.umd.js"></script>
thanks, @Fan Cheung talk a lot about how to combine multiple observable, to summarize you have two way to do that
// 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/[email protected]/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/[email protected]/dist/global/Rx.umd.js"></script>
Upvotes: 1
Views: 680
Reputation: 11345
try this
getFirstMenu$()
.map(firstMenuList => Observable.from(firstMenuList))
.flatMap(firstMenu=> getSecondMenu$(firstMenu.ID))
.do(secondMenu => firstMenu.child = secondMenu)
.subcribe()
edit1
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)
});
Upvotes: 1