为什么没有 RxJS 运算符来从流中删除特定项目?

Nik*_*vic 3 rxjs reactive angular

我在尝试从可观察流中删除属性时遇到了难以置信的困难。我有一个可观察的对象,它在 url ( Angular ActivatedRoute.queryParams) 中发出查询参数对象。我试图从发出的值中删除键和值并调用,distinctUntilChanged()以便它们的更改不会触发我的观察者。

允许pluck()您仅允许流中的一个参数通过,filter()允许您过滤整个流,skip()运算符允许您跳过整个流排放,throttle()以限制排放量。尽管做相反的事情pluck()- 您希望允许流中除一个值之外的所有值通过 - 并不存在。最接近完成它的是一个map(),它创建一个新对象,删除属性,然后返回该新对象,但这充其量是有问题的,而且通常不起作用。

除了我试图忽略的属性之外,我已采取为所有查询参数属性创建单独订阅的方法。我想必须有一个更好的方法来解决这个问题,是否有一些我缺少或解决的神奇操作符?当类似的东西存在时,为什么反应式库中缺少如此明显的运算符pluck()

编辑:

代码:

this.activatedRoute.queryParams
  .map((value) => {
    const newObj = Object.assign({}, value);
    delete newObj['page'];
    return newObj;
  })
  .distinctUntilChanged()
  .skip(1)
  .subscribe(
    (value) => console.log(value)
  );
Run Code Online (Sandbox Code Playgroud)

Mel*_*igy 5

看来您的代码不起作用的原因是具有相同属性和值的对象在 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)
  );
Run Code Online (Sandbox Code Playgroud)

您可以阅读JavaScript 中的对象比较 来了解更多比较对象的方法。

更新:

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

具体细节JSON.stringify()实际上并不是答案的核心,这就是为什么我链接到另一个专注于对象比较的答案,但是,简单的谷歌搜索显示了您可以使用的另一个答案: 排序对象属性和 JSON.stringify

要遵循答案,您需要更改此位:

  .distinctUntilChanged((oldProps, newProps) => 
    JSON.stringify(oldProps) === JSON.stringify(newProps)
  )
Run Code Online (Sandbox Code Playgroud)

变成这样的东西:

  .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);
  })
Run Code Online (Sandbox Code Playgroud)

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

  • 否决是不合理的,但很高兴您花时间来丰富答案 (2认同)