【发布时间】:2017-12-25 02:20:05
【问题描述】:
我有两个 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>
【问题讨论】:
-
ForEach .subscribe 看起来像是一种确保内存泄漏的可靠方法。即使没有嵌套的第二次调用
-
@c69 有什么好的方法可以避免内存泄漏?使用平面地图?
标签: javascript angular rxjs rxjs5