【问题标题】:Filter undefined from RxJS Observable从 RxJS Observable 过滤 undefined
【发布时间】:2023-04-03 12:41:01
【问题描述】:

是否有特定的习惯用法或实用程序用于从 RxJS 可观察对象中过滤 undefined?这段代码有我想要的行为:

obs.pipe(filter(x => x !== undefined))

一些替代品是

obs.pipe(filter(x => x)) // for all falsy values

obs.pipe(filter(Boolean)) // for falsy variables using Boolean ctor

【问题讨论】:

  • 您可以为此编写一个自定义运算符,但它可能不会比filter(Boolean) 短很多,即使这也会过滤掉所有false'' 等等。跨度>
  • obs.pipe(filter(x => x !== undefined)) 是我会使用的,简单易读

标签: typescript rxjs


【解决方案1】:

严格来说,单独使用过滤器来删除未定义的值并不能满足您的所有需求。它过滤掉未定义的值,但不会更改类型以指示未定义不再是可能的值。

在示例中:

const obs = new Subject<string | undefined>;
const stringObs = obs.pipe(filter(x => x !== undefined))

stringObs observable 仍然具有 Observable&lt;string | undefined&gt; 类型。

要解决这个问题,你需要使用:

const stringObs = obs.pipe(filter(x => x !== undefined) as OperatorFunction<string | undefined, string>)

如果您使用严格的空检查,这只是一个真正的问题,但如果您这样做(并且可以说您应该这样做),那么创建自定义运算符突然变得更有意义!类似的东西

function filterNullish<T>(): UnaryFunction<Observable<T | null | undefined>, Observable<T>> {
  return pipe(
    filter(x => x != null) as OperatorFunction<T | null |  undefined, T>
  );
}

完成这项工作。

然后您可以使用:

const stringObs = obs.pipe(filterNullish())

stringObs 的类型将是Observable&lt;string&gt;。 Typescript 能够正确推断出T 的类型,这让我印象深刻。

【讨论】:

  • 这个答案很棒,您提出了一个直截了当的问题,并且通过应用实际经验来解决微妙的打字问题,超出了所要求的范围!我唯一的小麻烦是您的 sn-p 依赖于与 filter(x =&gt; x != null) 的松散相等检查,因为我想确保使用严格的相等检查,所以我想我会使用 filter(x =&gt; !!x)filter(x =&gt; Boolean(t)) 代替。
【解决方案2】:

为了帮助打字稿理解未定义的值已被删除,一种方法是create a custom operator。另一种方法是通过user-defined type guard

function isDefined<T>(arg: T | null | undefined): arg is T {
  return arg !== null && arg !== undefined;
}

const obs = from(['hello', null, undefined]);
const filtered: Observable<string> = obs.pipe(filter(isDefined));

【讨论】:

    【解决方案3】:

    Rxjs 操作符被认为是低级的,旨在以一种可读的方式组合起来,以创建一个可以预测使用的结果 observable。有一个“实用程序”为你做这件事并不完全是我会(谦虚地)称之为“rxjs 方式”的方式。如果您所说的“成语”是一种约定,那么您的代码示例基本上就是您要查找的内容。

    我自己经常使用这种精确的过滤器模式,以至于我考虑过制作自定义运算符;但是,而不是这样:

    obs.pipe(filter(x => x !== undefined))
    

    你最终会得到这个:

    obs.pipe(notUndefined()) // or hasValue() or whatever you want to name it...
    

    这里没有很多节省。我会争辩说,您甚至没有节省可读性(或者说是完全边缘化的),这就是为什么我从来没有考虑过它的原因。不使用它的另一个理由是,过滤布尔值也很常见,这开始让你开始怀疑是否应该将两者结合起来以避免有太多令人困惑/类似的运算符,所有这些都可以很容易地创建无论如何都使用filter,等等……

    长话短说,我已经对这个确切的问题进行了很多思考,并且认为您只需使用您提供的代码示例。这是正确的”。它是“rx-js-y”。它是可读的。

    【讨论】:

      【解决方案4】:

      我认为我说你可以使用:

      obs.pipe(过滤器(x => x))

      也一样:

      obs.pipe(filter(x => x !== null && x !== undefined))

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多