*RxJs* 如何将多个 ajax 组合成一个不需要序列的可观察对象
*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>
return 其他订阅功能
// 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)
});
我有两个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>
return 其他订阅功能
// 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)
});