使用Observables进行递归

时间:2018-05-23 08:22:39

标签: angular typescript recursion rxjs

我需要在angular 2项目中使用REST API上传一个n-ary树。 我有一项服务允许我添加如下节点:

addNode(node: TreeNode, parentId: number): Observable<NodeJson>

TreeNode是一个对象:

{
  data: any,
  children: TreeNode[]
}

我需要父节点的id能够添加子节点,并且这个id在NodeJson对象中。

我目前的解决方案是:

uploadTreeNode(node: TreeNode, parentId: number) {
    this.node_service.addNode(node, parentId)
        .subscribe(uploaded_node => {
            for (let child of node.children) {
                this.uploadTreeNode(child, uploaded_node.id)
            }
        }

}

哪个工作正常,但这是我的问题:我需要知道整棵树的时间 已上传,这种方法无法实现,因为我在每次通话时直接订阅了observable,我无法知道它何时完成。

实际上,我正在努力实现这一功能:

uploadNodeTree(node: TreeNode, parentId: number): Observable<NodeJson>

一旦从儿童上传中的所有Observable完成后,会返回一个Observable。

有没有办法用Rxjs运算符做这样的事情?

1 个答案:

答案 0 :(得分:2)

正如所指出的那样,expand是正确的运营商。解决方案是上传第一个节点并使用expand创建来自其子节点的请求流并将其“附加”到源流,一旦没有更多子节点,只需发送empty()以结束流:

uploadTreeNode(node: TreeNode): Observabe<NodeJson> {
    return this.node_service.addNode(node, rootId)
        .map(uploaded_node => ({id: uploaded_node.id, current_node: node})
        .expand({id, current_node} => {
            if (current_node && current_node.children) {
                let reqs = current_node.children.map(n => this.nodeService.addNode(id, n))
                return Observable.merge(...reqs)
            } else {
                return Observable.empty()
            }
        })   
}

现在我能做到:

this.uploadTreeNode(myNode, 1).subscribe(uploaded_node => {
    console.log('Node has been uploaded: ' + uploaded_node),
})

感谢大家的帮助。

相关问题