在 ReactiveX 中调用数组实体和 children 的方法
Calling method on array entity and children in ReactiveX
我想从树中创建一个可观察对象。每个节点都会生成一个 observable,该 observable 取决于其 parent 的 observable(例如通过 switchMap
)。在树的每一层,每个 children 的可观察值都需要合并。
我想转换此代码以便它使用可观察对象:
interface Request {
name: string;
childrens?: Request[];
}
start() {
this.nextRequests(this.requests);
}
private nextRequests(requests: Requests[]) {
requests.forEach(request => {
this.socketService.message(request.name, (res) => {
if (request.childrens) {
this.nextRequests(request.childrens, res);
}
});
});
}
这就是我认为的样子:
interface Request {
name: string;
childrens?: Request[];
}
// This isn't right.
// SocketService.message return a observable, the reponse of the request.
start(requests: Request[]): Observable<any> {
return from(requests).pipe(switchMap(request => {
return this.socketService.message(request.name);
}), concatMap(request => {
if (request.childrens) {
return this.start(request.childrens);
}
return of(request.name);
}));
}
const mock: Request[] = [
{name: 'test1', childrens: [
{ name: 'test4' },
{ name: 'test5' }
]},
{ name: 'test2' },
{ name: 'test3' }
];
this.start(mock).subscribe((name) => {
console.log(`Request ${name} done`);
}, err => { }, () => {
console.log('Complete');
});
输出将如下所示:
Request test1 done
Request test2 done
Request test3 done
Request test4 done
Request test5 done
Complete
但我得到的是:
Request test2 done
Request test3 done
Request test4 done
Request test5 done
兄弟节点之间的发射顺序并不重要。但是带有 children 的 parents 没有被打印出来(test1
),并且永远不会执行完整的回调。这是为什么?
谢谢!
这里的主要问题是您没有将 test1
元素作为参数添加到
if (request.childrens) {
return this.start(request.childrens);
}
它应该看起来像
if (request.childrens) {
return this.start([{name:request.name},...request.childrens]);
}
通过这样做,您将收到订阅中的 test1
作为第一个值,否则它永远不会被记录,因为它会被流过滤。
编辑:
下面的link里也有BFS-ish demo
代码如下所示
function startBFS(requests) {
return merge(from(requests)).pipe(
mergeMap((x, i) => {
if (x.children) {
return concat(of(x), startBFS(x.children));
} else {
return of(x);
}
})
);
}
这是一个现场演示 codeSandbox
我想从树中创建一个可观察对象。每个节点都会生成一个 observable,该 observable 取决于其 parent 的 observable(例如通过 switchMap
)。在树的每一层,每个 children 的可观察值都需要合并。
我想转换此代码以便它使用可观察对象:
interface Request {
name: string;
childrens?: Request[];
}
start() {
this.nextRequests(this.requests);
}
private nextRequests(requests: Requests[]) {
requests.forEach(request => {
this.socketService.message(request.name, (res) => {
if (request.childrens) {
this.nextRequests(request.childrens, res);
}
});
});
}
这就是我认为的样子:
interface Request {
name: string;
childrens?: Request[];
}
// This isn't right.
// SocketService.message return a observable, the reponse of the request.
start(requests: Request[]): Observable<any> {
return from(requests).pipe(switchMap(request => {
return this.socketService.message(request.name);
}), concatMap(request => {
if (request.childrens) {
return this.start(request.childrens);
}
return of(request.name);
}));
}
const mock: Request[] = [
{name: 'test1', childrens: [
{ name: 'test4' },
{ name: 'test5' }
]},
{ name: 'test2' },
{ name: 'test3' }
];
this.start(mock).subscribe((name) => {
console.log(`Request ${name} done`);
}, err => { }, () => {
console.log('Complete');
});
输出将如下所示:
Request test1 done
Request test2 done
Request test3 done
Request test4 done
Request test5 done
Complete
但我得到的是:
Request test2 done
Request test3 done
Request test4 done
Request test5 done
兄弟节点之间的发射顺序并不重要。但是带有 children 的 parents 没有被打印出来(test1
),并且永远不会执行完整的回调。这是为什么?
谢谢!
这里的主要问题是您没有将 test1
元素作为参数添加到
if (request.childrens) {
return this.start(request.childrens);
}
它应该看起来像
if (request.childrens) {
return this.start([{name:request.name},...request.childrens]);
}
通过这样做,您将收到订阅中的 test1
作为第一个值,否则它永远不会被记录,因为它会被流过滤。
编辑:
下面的link里也有BFS-ish demo
代码如下所示
function startBFS(requests) {
return merge(from(requests)).pipe(
mergeMap((x, i) => {
if (x.children) {
return concat(of(x), startBFS(x.children));
} else {
return of(x);
}
})
);
}
这是一个现场演示 codeSandbox