代码之家  ›  专栏  ›  技术社区  ›  Nikola Jankovic

为什么没有RxJS操作符从流中删除特定项?

  •  2
  • Nikola Jankovic  · 技术社区  · 7 年前

    我在尝试从可观察到的流中移除属性时遇到了难以置信的困难。我有一个observable,它在url中发出查询参数对象(angular的 ActivatedRoute.queryParams ). 我正在尝试删除密钥(&m);从发出的值和调用 distinctUntilChanged() 这样它们的变化就不会触发我的观察者。

    这个 pluck() 允许您仅允许来自流的一个参数, filter() 允许您过滤整个流, skip() 操作员允许您跳过整个流排放, throttle() 限制排放量。尽管这样做与 拔毛() -您希望允许流中除一个值以外的所有值通过的位置不存在。最接近实现它的是一个map(),它创建一个新对象,删除属性并返回该新对象,但这充其量只是一个小问题,而且常常不起作用。

    我已经求助于为所有查询参数属性创建单独的订阅,但我试图忽略的一个除外。我想一定有更好的方法来解决这个问题,有没有什么神奇的操作员是我遗漏的或是我在做的?为什么反应式库中缺少如此明显的操作符 拔毛() 存在?

    编辑:

    代码:

    this.activatedRoute.queryParams
      .map((value) => {
        const newObj = Object.assign({}, value);
        delete newObj['page'];
        return newObj;
      })
      .distinctUntilChanged()
      .skip(1)
      .subscribe(
        (value) => console.log(value)
      );
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   Meligy    7 年前

    代码不起作用的原因似乎是在JavaScript中具有相同属性和值的对象被认为是不相等的,所以 distinctUntilChanged 不起作用,因为
    {prop: "value"} === {prop: "value"} false .

    有一个简单的解决方案。不建议将其用于长列表等,因为它在负载下表现不好,但如果只是路由更改,则不会很快更改多次。

    this.activatedRoute.queryParams
      .map((value) => {
        // Your existing code or
        const {page, ...otherProps} = value;
        return otherProps;
      })
      // You tell it what to use as comparison
      .distinctUntilChanged((oldProps, newProps) => 
        JSON.stringify(oldProps) === JSON.stringify(newProps)
      )
      // Not sure you still need this
      .skip(1)
      .subscribe(
        (value) => console.log(value)
      );
    

    有关比较中对象的更多方法,请阅读 Object comparison in JavaScript .

    更新:

    这个答案被否决了,因为 JSON.stringify() 据说有时提供不同顺序的属性。

    的详细信息 JSON。字符串化() 不是答案的核心,这就是为什么我链接到另一个侧重于对象比较的SO答案,然而,简单的谷歌搜索显示了另一个你可以使用的答案: sort object properties and JSON.stringify

    要遵循答案,请更改此位:

      .distinctUntilChanged((oldProps, newProps) => 
        JSON.stringify(oldProps) === JSON.stringify(newProps)
      )
    

    类似于:

      .distinctUntilChanged((oldProps, newProps) => {
        // You can put this at the beginning of the file
        // It doesn't need to live inside the RxJS operator
        const createComparisonString = 
            (obj) => JSON.stringify(obj, Object.keys(obj).sort());
    
        return createComparisonString(oldProps) === createComparisonString(newProps);
      })
    

    但再一次, JSON.stringify 不是比较对象的唯一方法。如果您愿意,请参阅上述答案以获取其他选项的示例。再一次 JavaScript中的对象比较 .