如何订阅一次可观察对象?

Posted

技术标签:

【中文标题】如何订阅一次可观察对象?【英文标题】:How to subscribe to an observable once? 【发布时间】:2020-09-16 12:34:28 【问题描述】:

我的函数access() 每次调用都需要订阅一次。

在下面的 sn-p 中,$valueChanges 为所做的每个更改发出数据。在没有const $ = ...$.unsubscribe() 的情况下调用access()$valueChanges observable 会发出不必要的值流。

是否有一个 rxjs 运算符/函数在函数内部的订阅中发出一次?即使该函数被多次调用,订阅也会发出一次?

access() 
  const $ = $valueChanges.pipe(
    map((res) => 
      ...
    ),
  ).subscribe((res) => 

    ...

    $.unsubscribe();
  );

【问题讨论】:

您的问题不清楚。您提供的代码将发出一次然后完成,无需取消订阅,除非您向of() 发送多个参数。查看文档here。如果您有更复杂的代码可能使用不同的 observable,请更新您的问题。请注意here 讨论的“完整”要求。 @dmcgrandle 是的,我将 of() 运算符更改为一些 valueChanges observable,它会在值更改时发出值。 然后更改问题的详细信息以显示您实际做了什么。到目前为止,您给出的内容没有您所描述的问题。更好的是,设置一个StackBlitz 来显示正在发生的问题。 感谢您提供更多信息。 $valueChanges 是否是一个热的可观察对象,无论是否订阅,它都一直在发射?如果是这样,当您调用access() 时,您是否希望$ 立即发出$valueChanges 发出的最后一个值(只要是过去),还是要等待@ 发出的下一个值987654339@,发出那个然后完成? $valueChangesBehaviorSubject(文档here)? 【参考方案1】:

试试shareReply(1)。然后原始流将只被调用一次,它的发射将与所有订阅者共享。如果流第二次发出 - 更新也将发送给所有订阅者。

access() 
  const $ = $valueChanges.pipe(
    map((res) => 
      ...
    ),
    // take(1), // in case if you need just 1 emit from it.
    shareReply(1), // in case if you don't want to trigger `$valueChanges` on every subscription.
  ).subscribe((res) => 

    ...

    // $.unsubscribe(); // it's useless in case of `take(1)`.
  );

【讨论】:

【参考方案2】:

您可以考虑使用take() 运算符,并在完成之前只发出第一个值。

根据documentation,take 运算符

Emit provided number of values before completing.

你可以这样使用它:

access() 
  valueChanges
    .pipe(
      map((res) => 
        ...
      ),
      take(1),
    ).subscribe((res) => 

      ...

    );

【讨论】:

以上是关于如何订阅一次可观察对象?的主要内容,如果未能解决你的问题,请参考以下文章

可观察的订阅总是一次发出

Angular - 竞争条件 - 一次多个订阅

发布订阅和观察者模式

创建一次性订阅

充电一次可走15460步,还能边走边充,这个机械假腿连脚趾都能动 | Science Robotics封面...

从一道面试题简单谈谈发布订阅和观察者模式