在 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