是否有一个等效的异步管道,您可以在组件内使用?

时间:2017-02-28 16:40:57

标签: angular rxjs reactive-programming

是否存在与async管道等效的东西,我可以在像

这样的组件中使用
   @Component({
      selector: 'my-component',
    })

    export class myComponent {

      myObservable$: Observable<string>;

      method() {
        doSomething(this.myObservable$);
        // here I would like to access directly the current string value of
        // myObservable$ without having to subscribe 
      }
    }

5 个答案:

答案 0 :(得分:4)

你必须问自己:你想通过避免subscribe()电话来达到什么目的?我的猜测是你要防止保留订阅并且不得不手动取消订阅。

如果是这种情况,您只需确保获得完成的Observable。然后没有必要在以后取消订阅。您可以将任何Observable(有限或无限)转换为最终完成的Observable。

以下是您案例的示例:

  method() {
    this.myObservable$.take(1).subscribe(
      val => doSomething(val)
    );
  }

正确的方法实际上取决于您的观察能力以及您想要对该值做什么。 Angular2 http调用例如自己完成no need to unsubscribe

或者如果你想为你的observable中的每个新值调用doSomething,上面的解决方案都不合适,因为你只得到第一个值,然后observable就完成了。正如我所说,这归结为问题的背景。

答案 1 :(得分:1)

不,没有。您需要手动订阅并手动取消订阅以避免内存泄漏。

对于简单的订阅,您可能会想要这样做:

@Component({
  selector: 'my-component',
})
export class myComponent implements OnInit, OnDestroy {
  public myObservable$: Observable<string>;
  private myObservableSub: Subscription;

  ngOnInit() {
    this.myObservableSub = this
      .myObservable$
      .subscribe(_ => {
        // do something
      });
  }

  ngOnDestroy() {
    this.myObservableSub();
  }
}

但是如果你有很多订阅怎么办? 你应该做点什么:

@Component({
  selector: 'my-component',
})
export class myComponent implements OnInit, OnDestroy {
  public myObservable1$: Observable<string>;
  private myObservableSub1: Subscription;

  public myObservable2$: Observable<string>;
  private myObservableSub2: Subscription;

  public myObservable3$: Observable<string>;
  private myObservableSub3: Subscription;

  ngOnInit() {
    this.myObservableSub1 = this
      .myObservable1$
      .subscribe(_ => {
        // do something
      });

    this.myObservableSub2 = this
      .myObservable2$
      .subscribe(_ => {
        // do something
      });

    this.myObservableSub3 = this
      .myObservable3$
      .subscribe(_ => {
        // do something
      });
  }

  ngOnDestroy() {
    this.myObservableSub1();
    this.myObservableSub2();
    this.myObservableSub3();
  }
}

<小时/> 答案不是

您应该执行以下操作:

@Component({
  selector: 'my-component',
})
export class myComponent implements OnInit, OnDestroy {
  private componentDestroyed$ = new Subject<void>();

  public myObservable1$: Observable<string>;
  public myObservable2$: Observable<string>;
  public myObservable3$: Observable<string>;

  ngOnInit() {
    this
      .myObservable1$
      .takeUntil(componentDestroyed$)
      .subscribe(_ => {
        // do something
      });

    this
      .myObservable2$
      .takeUntil(componentDestroyed$)
      .subscribe(_ => {
        // do something
      });

    this
      .myObservable3$
      .takeUntil(componentDestroyed$)
      .subscribe(_ => {
        // do something
      });
  }

  ngOnDestroy() {
    this.componentDestroyed$.next();
    this.componentDestroyed$.complete();
  }
}

如果您想了解更多相关信息,请参阅 Ben Lesh 的优秀文章:https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87

编辑:
感谢@olsn,我编辑了我的答案并添加了next的行,因为确实完整的不会阻止其他流。

我创建了一个小型的Plunkr来演示这种行为:https://plnkr.co/edit/dcueDqUgpqgYimxEAGUn?p=preview

答案 2 :(得分:1)

如果您位于Component或可以访问ChangeDetectorRef的地方,则可以执行以下小技巧:

@Component({
...
  providers: [AsyncPipe]
})
export class ExampleComponent {
  app$ = this.sandbox.allApps$;
  apps = this.pipeAsync.transform(this.app$);

  contructor(
    protected pipeAsync: AsyncPipe,
    protected sandbox: AppAppsSandbox
  ) {}
}

这假定访问了名为AppAppsSandbox的服务,但是Observable app$可以来自任何地方,这是拆包的便捷方法。

答案 3 :(得分:0)

您可以实现目标(不使用预订)的唯一方法是使用BehaviorSubject,它具有方法getValue()。可观察对象和BehaviousSubjects之间有一些区别(您可以在documentation中找到它们)。

var subject = new Rx.BehaviorSubject(current_subject_value);
subject.getValue()

然而,有一些关于堆栈溢出的争论,为什么不应该使用getValue方法,而是使用订阅...但是有一个可观察的take运算符,它将完成可观察的序列(因此不必管理订阅)

this.myObservable$.take(1).subscribe()

答案 4 :(得分:0)

你可以使用我的图书馆。您可以创建 useReader 挂钩并将其包装在 AsyncPipe 组件中。看看例子。 https://www.npmjs.com/package/reactivex-react