每个服务器响应+延迟后轮询服务器

问题描述 投票:2回答:3

我正在研究一种效果,即轮询服务器。

我想要实现的目标如下:

1)向服务器发送GET请求

2)收到响应后,等待3秒钟

3)发送相同的GET请求

4)收到响应后,等待3秒钟

5)发送相同的GET请求

... 等等。

我现在拥有的代码并不常用,因为无论是否收到响应,它每3秒轮询一次服务器:

@Effect()
pollEntries$ = this.actions$.pipe(
  ofType(SubnetBrowserPageActions.SubnetBrowserPageActionTypes.StartPollingSubnetEntries),
  switchMap(() => {
    return timer(0, 3000);
  }),
  takeUntil(this.actions$.pipe(ofType(SubnetBrowserPageActions.SubnetBrowserPageActionTypes.StopPollingSubnetEntries))),
  switchMap(() => {
    return this.subnetBrowserService.getSubnetEntries();
  }),
  map((entries) => {
    return new SubnetBrowserApiActions.LoadEntriesSucces({ entries });
  }),
  catchError((error) => {
    return of(new SubnetBrowserApiActions.LoadEntriesFailure({ error }));
  }),
);

我正在努力的另一件事是如何停止投票。如果我在请求发送到服务器之前发出StopPollingSubnetEntries动作,那么它工作正常 - 但是如果我在发送请求后发出它,那么在轮询停止之前我会再收到一个后续响应。

angular rxjs ngrx rxjs6 ngrx-effects
3个回答
1
投票

您可以使用expand连续映射到下一个http请求并预先添加delay

const stopPolling$ = this.actions$.pipe(
  ofType(SubnetBrowserPageActions.SubnetBrowserPageActionTypes.StopPollingSubnetEntries)
);

const httpRequest$ = this.subnetBrowserService.getSubnetEntries().pipe(
  map(entries => new SubnetBrowserApiActions.LoadEntriesSucces({ entries })),
  catchError(error => of(new SubnetBrowserApiActions.LoadEntriesFailure({ error })))
)

const pollEntries$ = this.httpRequest$.pipe(
  expand(_ => of(1).pipe(
    delay(3000),
    mergeMap(_ => this.httpRequest$),
  )),
  takeUntil(this.stopPolling$)
);

要开始投票,您必须订阅pollEntries$

startPolling() {
  this.pollEntries$.subscribe(entries => console.log(entries));
}

或者在您的动作发出时映射到pollEntries

const pollEntriesOnAction$ = this.actions$.pipe(
  ofType(SubnetBrowserPageActions.SubnetBrowserPageActionTypes.StartPollingSubnetEntries),
  switchMap(() => this.pollEntries$)
);

this.pollEntriesOnAction$.subscribe(entries => console.log(entries));

https://stackblitz.com/edit/angular-mu3kp5


2
投票

我认为你很接近而不是switchMaptimer你可以使用和delay()take(1)repeat()

const stop$ = this.actions$.pipe(ofType(SubnetBrowserPageActions.SubnetBrowserPageActionTypes.StopPollingSubnetEntries));

@Effect()
pollEntries$ = this.actions$.pipe(
  ofType(SubnetBrowserPageActions.SubnetBrowserPageActionTypes.StartPollingSubnetEntries),
  switchMap(() => this.subnetBrowserService.getSubnetEntries().pipe(
    catchError(...),
    delay(3000),
    take(1),
    repeat(),
    takeUntil(stop$),
  )),
);

0
投票

我写了一篇关于这个主题的博客文章 - https://bbonczek.github.io/jekyll/update/2018/03/01/polling-with-ngrx.html

我决定创建一些小效果,当它们一起工作时 - 将轮询服务器。码:

@Injectable()
export class SubnetEffects {
  constructor(
    private actions$: Actions<SubnetActions.SubnetActionsUnion>,
    private http: HttpClient
  ) {}

  private isPollingActive = false;

  @Effect()
  startPolling$ = this.actions$.pipe(
    ofType(SubnetActions.SubnetActionTypes.StartPollingSubnetDevices),
    map(() => this.isPollingActive = false), // switch flag to true
    switchMap(() => {
      return this.http.get<SubnetEntry>('http://localhost:5000/api/subnet').pipe(
        switchMap(entries => new SubnetActions.GetSubnetDevicesSucceded({ entries })),
        catchError(error => of(new SubnetActions.GetSubnetDevicesFailed({ error })))
      ),
    }),
  );

  @Effect()
  stopPolling$ = this.actions$.pipe(
    ofType(SubnetActions.SubnetActionTypes.StopPollingSubnetDevices),
    map(() => this.isPollingActive = false) // switch flag to false
  );

  @Effect()
  continuePolling$ = this.actions$.pipe(
    ofType(
      SubnetActions.SubnetActionTypes.GetSubnetDevicesSucceded,
      SubnetActions.SubnetActionTypes.GetSubnetDevicesFailed
    ),
    takeWhile(() => this.isPollingActive), // do this only as long as flag is set to true
    switchMap(() => {
      return this.http.get<SubnetEntry>('http://localhost:5000/api/subnet').pipe(
        delay(5000),
        switchMap(entries => new SubnetActions.GetSubnetDevicesSucceded({ entries })),
        catchError(error => of(new SubnetActions.GetSubnetDevicesFailed({ error })))
      );
    })
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.