使用异步管道来轮询Observables?

时间:2017-04-13 09:38:42

标签: angular typescript protractor rxjs

情景:

我有一个每2秒轮询一次网址的服务:

export class FooDataService {

...

  public provideFooData() {
    const interval = Observable.interval(2000).startWith(0);
    return interval
      .switchMap(() => this.http.get(this.requestUrl))
      .map(fooData => fooData.json())
  }
}

现在我有一个组件,我想显示这个轮询数据:

export class FooComponent implements OnInit {

  constructor(private fooDataService: FooDataService) {}

  public fooData$: Observable<FooData>;

  ngOnInit() {
    this.fooData$ = this.fooDataService.provideFooData();
  }
}

在组件模板中,我将使用异步管道检索并将值传递给子组件:

<foo-data-viewer [data]="fooData$ | async"></foo-data-viewer>

这种方法的问题:

使用量角器无法测试这样做(请参阅我的last question on this topicthis article)。所有代码都在ngZone中执行,量角器将等待所有排队的操作完成后再继续。但Observable.interval()将排列无限数量的操作,从而导致量角器超时。

常见解决方案:

我最常阅读的修补程序是使用runOutsideAngular,如下所示:

export class FooComponent implements OnInit, OnDestroy {

  constructor(private ngZone: NgZone,
              private fooDataService: FooDataService) {}

  public fooData: FooData;
  public fooDataSubscription: Subscription<FooData>;

  ngOnInit() {

    this.ngZone.runOutsideAngular(() => {
      this.fooDataSubscription =
        this.fooDataService.provideFooData()
            .subscribe(
               fooData => this.ngZone.run(() => this.fooData = fooData)
            );
    });
  }

  ngOnDestroy(): void {
    this.fooDataSubscription.unsubscribe();
  }
}

通过在ngZone之外运行间隔,量角器不会等到轮询完成后再继续,因此不会超时。

但这意味着:

  • 我无法使用async管道,我必须手动订阅。
  • 我必须手动管理订阅,并在组件销毁时自行清理它。
  • 我无法保持漂亮和干净的Observable风格,代码变得更加复杂,特别是如果我有多个轮询服务。

我的问题:

在运行ngZone之外的时间间隔时,是否有办法保持功能性rxjs样式并继续使用异步管道(或等效管道)?

我偶然发现this github project看起来就像我想要的那样,但我无法让它发挥作用。

我需要的是在我的场景中离开和重新进入区域的工作示例,而无需自己管理订阅。

1 个答案:

答案 0 :(得分:0)

 onlyWon = df.loc[df['Sales stage'] == "Won"]

 sales_no_won = onlyWon['Sales No']
 reults = df2.query('`Sales No` in @sales_no_won').copy()

Stackblitz