【问题标题】:Wait for Subscription set Recursively to Complete等待订阅集递归完成
【发布时间】:2019-10-15 15:26:57
【问题描述】:

我有一个带有子对象的数组,并且需要递归地在每个对象中设置一个字段(隐藏)。每个值都在订阅中设置。我想等到数组中的每一项都递归更新后,再订阅完成。

隐藏字段将根据从另一个 observable 派生的角色和权限进行设置。在示例中,我添加了延迟来模拟它。

这是我的第一次尝试。我敢肯定有一种更清洁的方法来解决这个问题。

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 和递归 SetHidden。如果可能,我也想避免使用主题。

【问题讨论】:

    标签: rxjs rxjs6


    【解决方案1】:

    这是我的方法:

    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,这意味着它会自动订阅/取消订阅其内部 observable。

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

    在这种情况下,您必须处理大量 Observables-of-Observables(higher-order observables),这就是为什么每次遇到children 财产。该属性中的任何子对象都可以拥有自己的 children 属性,因此您必须确保 Observable 包含 only first-order Observables。

    您可以阅读更多关于高阶和一阶可观察对象here

    Here is a CodeSandbox example

    【讨论】:

    • 谢谢。这有帮助!
    猜你喜欢
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多