等待递归设置完成

时间:2019-10-15 15:26:57

标签: rxjs rxjs6

我有一个带有子对象的数组,需要递归地在每个对象中设置一个字段(隐藏)。每个值都在预订中设置。我想等到订阅中的递归更新数组中的每个项目之前。

将基于从另一个可观察对象派生的角色和权限来设置隐藏字段。在示例中,我添加了一个延迟来模拟。

这是我的第一遍。我敢肯定有一种更干净的方法来解决这个问题。

https://codesandbox.io/s/rxjs-playground-hp3wr

// Array structure. Note children.
const navigation = [
  {
    id: "applications",
    title: "Applications",
    children: [
      {
        id: "dashboard",
        title: "Dashboard"
      },
      {
        id: "clients",
        title: "Clients"
      },
      {
        id: "documents",
        title: "Documents",
        children: [
          {
            id: "dashboard",
            title: "Dashboard"
          },...
        ]
      },
      {
        id: "reports",
        title: "Reports"
      },
      {
        id: "resources",
        title: "Resources"
      }
    ]
  }
];

在代码沙箱示例中,查看控制台消息,我得到了正确的结果。但是,我想避免必须订阅setHidden和recursivelySetHidden。我也想避免使用Subject。

1 个答案:

答案 0 :(得分:0)

这是我的方法:

const roleObservable = timer(1000).pipe(mapTo("**************"));

function populateWithField(o, field, fieldValue) {
  if (Array.isArray(o)) {
    return from(o).pipe(
      concatMap(c => populateWithField(c, field, fieldValue)),
      toArray()
    );
  }

  if (o.children) {
    return roleObservable.pipe(
      tap(role => (fieldValue = role)),
      concatMap(role => populateWithField(o.children, field, role)),
      map(children => ({
        ...o,
        [field]: fieldValue,
        children
      }))
    );
  }

  return roleObservable.pipe(
    map(role => ({
      [field]: role,
      ...o
    }))
  );
}

of(navigation)
  .pipe(concatMap(o => populateWithField(o, "hidden")))
  .subscribe(console.log, e => console.error(e.message));

要注意的主要事情是频繁使用concatMap。它是higher-order mapping operator,这意味着除其他外,它将自动从其内部可观察的对象中订阅/取消订阅。

concatMap与其他运算符的不同之处在于,它会保留发射值的缓冲区,这意味着它将等待等待当前内部的可观察在订阅下一个之前完成。

在这种情况下,您必须处理很多Observables-of-Observables(higher-order observables),这是为什么,您必须每次使用concatMap遇到children属性的时间。该属性中的任何子级都可以拥有自己的children属性,因此您必须确保Observable包含 一阶 Observable。

您可以了解有关高阶和一阶可观察物here的更多信息。

Here is a CodeSandbox example